Jump to content

Recommended Posts

I have a hierarchy of classes. Call them Grandparent, Parent and Child.

I have a dynamic dispatch VI in grandparent that child overrides.

In the child implementation, I want to access data in the parent class control.

The template in the grandparent has two inputs of type grandparent. The dynamic one and a static one. The dynamic one is used to dispatch to the correct child.

(this is because grandparent has more than one parent sub class and these have more than one child subclasses)

The static one is used to pass in a parent object so the child has access to its data between calls. (the child is actually a message not spawned from the original parent object and therefore does not contain this persistent parent data)

What I need to do is cast the grandparent wire to the type of parent so I can access the parent's data. I could use the child to do this but how do I extract the parent class type from the child and use it to cast the grandparent to type parent? I need to do this statically as design time, not at runtime.

thanks for any ideas.

-John

An alternative solution would involve having the child (message) object inherit the data in the parent object so I could access it via property nodes. Not sure if that is possible.

Link to post
Share on other sites

Well, it is kinda complex, but here goes:

I am trying to make a messaging system that uses the class hierarchy to route messages and has a plug-in type of implementation for routing methods.

So, I have three main classes: System, Process and Transport.

System holds a DVR containing an array of Process classes.

Process holds a Transport object.

Specific transports types (local queue, remote network message, notifier, etc) inherit from the transport class.

Specific processes inherit from the process class.

Each specific process class has child messages that implement create, send and execute methods.

First, you instantiate an object of type System and create the DVR to hold the data.

Next, you create a transport object for the specific type of transport you want a process to use.

You then create a object for the specific process that will use that transport and store the transport in the process's (parent) private data. You also add this process object to the system object DVR.

Later in your application, you create a instance of the specific process (can be the same as the object used to set the transport, or just another instance) and you set any initial conditions (this specific process, called the parent in the original email, stores any data needed to be accessed between messages). This then passes to a loop that waits for a message using the transport type set for that process and then calls the execute method for the message sent.

The advantage of this is almost everything in the architecture is reusable. You just define the specifics by creating you specific processes and their messages and a transport implementation.

The disadvantages are you can only have one implementation of a specific process class in each application instance.

The other disadvantage is I cannot figure out how to cleanly access the data in the specific process (the parent) from within the execute message method. I have for now cast the process object to the type of the specific process but I would rather do this a better way.

I included a zip of the demo project so far. Feel free to tell me this is a crazy way to solve this problem.

Message System.zip

-John

Link to post
Share on other sites

I need to install the latest LabVIEW version to look at your code, but some of what you describe sounds very similar to what I’ve done. My Transports are called “Messengers”, and I have “Actor” objects that contain a Messenger that is the method to send messages to a process running in parallel. But other stuff mystifies me. It sounds like you have message classes as the children of your Process classes; but aren’t messages and processes entirely different things.

Link to post
Share on other sites

What I need to do is cast the grandparent wire to the type of parent so I can access the parent's data. I could use the child to do this but how do I extract the parent class type from the child and use it to cast the grandparent to type parent? I need to do this statically as design time, not at runtime.

Umm, since class data is always private, you're not going to be able to do this directly in the child class (you could, in principle, cast a grandparent to parent within the parent class method and then access the class data but it would be prone to failures ince you'd have no way of guaranteeing the cast would succeed). The best you can do is created protected class data accessors in the parent class and use them in the child class to get at the class data.

Link to post
Share on other sites
aren’t messages and processes entirely different things.

The architecture I am trying to design is one of a process that has a defined API. So, instead of having a method for each thing the process can do, it has a message (API call) that it can process. So, it made sense to me that these would be children of the process since they were exclusive to the process and operated on the process' private data. Also, by having them be children, I can use the inheritance mechanism to allow my message system to detect what process owns them and then route the message to the process using its chosen transport automatically.

Again, this may turn out to be a bad idea, but I am going to try going down this road as far as it will take me until I make it work or decide it is the wrong road.

The best you can do is created protected class data accessors in the parent class and use them in the child class to get at the class data.

So I have created those accessors in the parent, but the wire type coming into the child is of type grandparent. So, I don't have access to the parent methods without casting it to the parent's type. I was hoping there was a way to do this using the child class wire. But I cannot sort out how to do this.

Link to post
Share on other sites

So I have created those accessors in the parent, but the wire type coming into the child is of type grandparent. So, I don't have access to the parent methods without casting it to the parent's type. I was hoping there was a way to do this using the child class wire. But I cannot sort out how to do this.

Ok, but you can cast the grandparent wire to parent wire using a "to more specific class" node and then call the accessors. You probably want to check the error code from the to more specific class node just in case you accidentally get something which can be treated as a parent class (note that the to more specific/generic class conversion odes are operating on the wire type not the actual data type).

I think, however, that there may be some refactoring you could do with the design - normally when one is facing a series of uphill battles like this it's better to find a way that is downhill :-) !

Link to post
Share on other sites

you can cast the grandparent wire to parent wire using a "to more specific class" node and then call the accessors.

That s what I did. But that means I needed a static parent object on the BD of the child method. I assume that means I had to allocate the memory for the parent's private data even though I did not use it. Seems inefficient to me. I would rather use the child wire to accomplish that. But this gives me an idea I need to go try now...

Link to post
Share on other sites

ok, so this is weird. If you take the grandparent wire with the parent object riding on it and cast that to the parent type, you can use the parent accessors to get at the data in the parent object.

But, if you take the grandparent wire with the parent object riding on it and you cast it to the child, then try to use the parent accessors available to the child class (I made them protected), you don't get the data. It comes back empty. Turns out, this is because the cast fails. But this was not obvious to me at first because I did not get an error message, even though I have automatic error handling turned on.

Link to post
Share on other sites

ok, so this is weird. If you take the grandparent wire with the parent object riding on it and cast that to the parent type, you can use the parent accessors to get at the data in the parent object.

But, if you take the grandparent wire with the parent object riding on it and you cast it to the child, then try to use the parent accessors available to the child class (I made them protected), you don't get the data. It comes back empty. Turns out, this is because the cast fails. But this was not obvious to me at first because I did not get an error message, even though I have automatic error handling turned on.

It's not very weird. You just cast a parent object to a child. You can't do that - it's a parent object and not a child object and casting it to a child doesn't change that fact.

Remember, casting is just about changing the wire type - you're not actually casting the data that is travelling on the wire. If you want to do the latter, then the preserve run time class node is your friend - but you'd better be sure that the data your messing with is really the right type (i.e. you still can't make a parent into a child). I guess the lack of error reproting is down to the casting class being a primitve rather than a subvi. (herein casting==to more specific class/to more generic class)

Life was so much simpler before inheritance came along :-) !

Link to post
Share on other sites

It was the lack of error dialog that was weird. I understand why the cast did not work.

Still, it is a bummer that I cannot extract a parent object from the child object without creating a parent object to feed into the to more generic node.

It may not be such a killer. The child objects have to have the parent (and grandparent) in memory anyway, so the penalty is the memory allocation of the default data for the parent's private data. I'd imagine that large data storage in a class would be in an array or other dynamically growable object (like a waveform or variant). So long as you don't set the default value of tge class private data to contain lots of data, the actualy overhead of storing e.g. empty arrays is not so large.

  • Like 1
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Similar Content

    • By CraigC
      Hello,
      Bit of an odd one and I am probably doing something fundamentally wrong however I am fairly new to OOP.  Essentially I have a hierarchy of 3 items say A, B and C.  I have a DD VI called "ModifyUI.vi" in each class and I am calling this VI and its parents in parrallel (Probably not a great idea but it is my end goal).  After each "ModifyUI.vi" has completed doing what it needs to I would then like to collect each VI's data as they were all run in parrallel back into the initial class that called them all.
      I have attached an overview of what I am trying to achieve in a mockup of my problem.  I am willing to change tack as long as the same goal is reached (Modify all class data in parrallel).
      Thanks in advance
      Craig
      Lava Temp.zip

    • By LogMAN
      Hello everyone, I want to share a VI that I recently created to search for orphan files in a (very! ) messy project. As it turned out it's actually very easy to do that (if you find super-secret stuff on the net):

      This VI will find files (VIs, Controls, Classes, etc...) in your project folder that are not linked by a given top-level VI. This is done by comparing the call-chain of the top-level VI with the files on disk. It assumes your files are in folders relative to the specified root directory. This also means that files outside the hierarchy will be ignored (vi.lib and such).
      Be aware of (at least) two things:
      This VI will return false friends if you happen to have any "Open VI Reference" call with constant VI names or paths connected to it (not a problem if you use static VI references). VIs in diagram disable structures are not listed in the call-chain. So if you use conditional (or regular) disable structures this VI will return false friends. Does anyone know a solution to number 2. actually?
      Hope this proves useful to you too.
    • By LewisG
      Hi all,
       
      I'd appreciate some advise or pointing in the right direction regarding building an EXE with class dependencies.  I have a project built with actor framework and when I build it to exe, I get lots of dependencies which I think should be included in the EXE as seen below:
       
       
       
      On my Source files build properties page I currently have nothing under Always Included.  I did try including all of the lvlibs and including them in the EXE but it didn't make a difference.
       
      In summary, I think the way my EXEs are building is not right.  It is easy to see what VIs I'm using (although you can't open them) and it doesn't look very professional.  What are the best practices for building dependencies into EXE?
       
      Thanks
       
       
    • By Reds27
      If you have your class and you want to create a pull right menu on a property node for it, you can use the colon ( to separate property items for it. Just right click on the class » Properties » Item Settings » Localized name.
       

       
      Also, on a separate note and since I'm in the neighborhood, you could also take advantage of the "Documentation" tab in the Class properties to change the "Localized name" from the default (in my case, "NI_VSA.lvclass") to something shorter or more meaningful. .This makes it easier on the eye.
       
      Regards
    • By John Lokanis
      Goal:
      Find the best methods (or at least some good options) for message decoupling that are simple to implement and efficient to execute.
      Background:
      Messaging architectures in LabVIEW that use a class for each unique message type are strongly coupled to the recipient process (aka ‘Actor’).  This is due to the need within the message execution code (a method of the message class) to access the private data of the recipient process or to call methods in the recipient process in order to do the work that the message intends.  (See Actor Framework for an example of this).
      The problem arises when you wish to send these messages across a network between two separate applications.  In most cases, these applications are not duplicates of each other, but rather serve completely separate purposes.  An example would be a client and a server.  The client needs to message requests to the server and the server needs to push data to the client.  For a process to send a message, it needs to package the inputs in the private data of the message class and then transmit it via the network transport (which can be implemented in multiple different ways and is not material to this discussion).  In order to construct the message, the sender will need a copy of the message class included in their application.  This will mean they will need to also load the class of the message recipient since it is statically linked to the message class within the method that executes the message.  And since that will trigger many other class dependencies to load, the end results is the majority of the classes in the recipient application will need to be included in the sending application.  This is not an optimal solution.
      So, we need to find a way to decouple messages from their recipients but still be able to execute them.
      My solution:
      The way I have been handling this is for each message that needs to cross the network I create a message class whose execute method calls an abstract method in a separate class (call this my network message execution class).   Both the sender and the recipient will have a copy of these message classes and the network message execution class.  Inside the message class’s execution method, I access a variable that stores an instance of the network message execution class and then calls the specific abstract method in the network message execution class for this particular message.
      In each recipient application, I create a child of the network message execution class and override the abstract methods for the messages I intend to receive, placing the actual execution code (and static links to the recipient process) within the child class methods.
      Finally, when each application initializes, I store its child network message execution class in the aforementioned variable so it can be used to dynamically dispatch to the actual method for message execution.
      The advantages of this are:
      Messages are decoupled between my applications.
      The disadvantages are:
      For each message I wish to transmit, I must create a new message class, a method in the network message execution class and a method override with the real implementation in the recipient’s network message execution class child and then edit the message class to call the method in the network message execution class.
      This also means that each application must have a copy of all the message classes passed between applications and the network message execution class.

      The problem arises when you add a 3rd or fourth application or even a plugin library to the mix and wish to decouple those from the other applications.  You must either extend the current set of messages and the abstract methods in the network message execution class, having each entity maintain a copy of all of the messages and the network message execution class even though they never send or receive most of those messages, or you must add additional variables to your application to store different implementations of the network message execution class for each link between entities.
      So, now that you have read my long explanation, does anyone have ideas for a better way to solve this?  I would love to simplify my code and make it easier to maintain, while retaining the functionality that class based message architectures offer.  But decoupling must be addressed somehow.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.