LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

load class from XML (Dynamic Dispatch)

I'm continuing my voyage into the realms of LVOOP..... :smileyhappy:

 

I have encountered a new problem which I am sure there's a solution to.....

 

I have a certain hierarchy and I want to implement a single save and load routine for all objects int he hierarchy (located int he parent class of course).

 

Using the "flatten to XML" I'm able to create some nice XML files with all parent and sibling information saved (as long as the values are non-default of course).

 

Where I am running into problems is the loading of the data within this XML file.  I want to be able to take an object and basically re-initialise it to the values within the file.  All fine and good I thought, but it doesn't work.

 

Load class from XML.PNG

 

The problem is that when using the VI with Dynamic dispatch inputs, the output of the "Unflatten from XML" is giving me a conflict with the Dynamic dispatch output saying the obejct types do not  necessarily match.  Is it not possible to match the object type on the input and output of the "Unflatten from XML" primitive?

 

If I try removing the "Dynamic Dispatch" input to a static input, then it only loads the data for the parent class regardless of the actual input class.

 

Am I doing something silly here or is there no other way to properly load a sibling class from a file using only a method residing within the parent class?  I was hoping I could have a single "Save-Restore" function residing within my parent class to make life easier for me.

 

Shane.

Message Edited by Intaris on 06-17-2009 05:24 AM
0 Kudos
Message 1 of 17
(5,945 Views)

I have found a REALLY ugly workaround which at least 99.99% of the time delivers correct data.

 

Feast your eyes on this monstrosity....  Smiley Surprised

 

 Load class from XML workaround.PNG

 

Input and output Terminals are Dynamic Dispatch and I've tried it on a few different sibling classes and it seems to work fine.  There IS the race condition problem of course since we're not able to put the output terminal in a structure (to force a sequence).

 

Please somebody tell me there's a better way to do this...

 

Shane

Message Edited by Intaris on 06-17-2009 06:59 AM
0 Kudos
Message 2 of 17
(5,930 Views)

For the race condition, you could probably add a wait before the case structure, which would probably increase your percentage to 99.9999. 😄

 

Can't you cast the LVClass wire (at least I'm assuming that's what it is) to the parent class?


___________________
Try to take over the world!
0 Kudos
Message 3 of 17
(5,927 Views)

Hi Tst,

 

Problem is that in order for the cast to yield any useful results, I have to make the inputs and outputs non-Dynamic which results in ONLY the data for the parent class being loaded.

 

If the inputs and outputs are Dynamic, then a cast will not solve the problem (It could be a grandchild class being cast as a child, thus breaking the dynamic dispatch tables).

 

The only solution I see is for the "UnFlatten from XML" to RETAIN the true object type.

 

Either that or use my beautiful solution  :smileytongue:

 

Shane.

 

Ps I just did a bit of a test of the race condition probabilities.  I ran 100000 tests (100k) with a program stressing both cores AND ram of my machine in parallel and all 100k of 100k iterations worked out OK.  I suppose that lets me think I should be in the range of at least 99.99%.......  :smileyvery-happy:

0 Kudos
Message 4 of 17
(5,925 Views)

Here's a question.....

 

Does the property node force the VI into single-thread operation (UI thread)?

 

Would this assure no race condition?  I don't think so, but I'm surprised I'm not able to provoke a race condition.

 

Shane.

0 Kudos
Message 5 of 17
(5,923 Views)

You need to preserve a chain of VIs that don't break the dynamic dispatch wire...since the type of data the XML primitive sees can't be determined at compile time, your VI will never be able to ensure that a proper object will be returned to the output.

 

You get around this problem by creating a temporary object for deserialization, then copying its data to the wire for your dynamic dispatch, demonstrated below. You might wish to create a more robust cloning set of VIs than what's pictured, and better error handling, but it gets the idea across...

 

 dynamic-load.png

0 Kudos
Message 6 of 17
(5,915 Views)

Hi Kegghead,

 

getting around the necessity for this "Get all data" and "Set all data" accessor methods (plus handling of ALL parent values recursively)  is what led me to try a universal approach.

 

Funnily enough, the XML primitive seems to do a pretty GOOD job of interpreting the correct class when deserializing.  My method described above would not work otherwise.  The output also has the correct class type when returned.

 

I've made a suggestion on the LV Idea Exchange for a SPECIFIC LVOOP cast option to enable us to satisfy the Dynamic Dispatch requirements without having to jump through any loops.

 

Shane.

0 Kudos
Message 7 of 17
(5,912 Views)

OK, my method essentially BREAKS the dynamic dispatch idea.

 

If I try to unflatten a sibling string with a parent class as input the output data type of the DYNAMIC DISPATCH output is NOT the correct type..... Ouch.

 

The Unflatten from XML seems to perform a cast from a sibling to a parent if there is a mis-match between XML string and input object.  Obviously, it returns an error if the input object is a sibling of the XML string (no data to do a proper cast).

 

It would be cool if we had an Unflatten from XML function which did ONLY returned values if the two types are truly identical.

 

Shane.

0 Kudos
Message 8 of 17
(5,906 Views)

The only way I could see doing this is to unflatten the data as a generic base class which all your serializable objects would inherit from. That class would need to then define the magical "clone everything" method. No, it's not pretty, but I can't think of another way other than variants of what you've shown. I remember some VIs called something like "Read Anything" and "Write Anything" written by a third party (MGI I think?) that might be able to provide insight into how to make a generic clone method...all I can say is it can be done.

 

The fundamental problem you're facing is the primitives all require types to be known at compile time, which flies in the face of what a dynamic dispatch is all about: determining the type at run time. That, and that LV OOP really lacks a built in framework that more mature OOP based languages can take advantage of and do this stuff easily.

0 Kudos
Message 9 of 17
(5,897 Views)

Interestingly enough, the Unflatten from XML seems to be fairly Class-aware.  It returns an Error 1400

 

Possible reason(s):

LabVIEW:  Attempted to read flattened data of a LabVIEW class. The flat data could not be converted to the requested type because the flat data is not the same as the requested type nor is it the same as any child class of the requested type.


So it seems to be able to cast when appropriate.  I would just wish it to return an error when a cast int he OTHER direction is also attempted (perhaps a boolean input to make an EXACT cast?).

 

Shane.

0 Kudos
Message 10 of 17
(5,894 Views)