Re: XControls: Dynamic loading & polymorphism



The code promised in my last post is attached in "foofun.zip". It has the following things:

- Two XControls, each named "foo". One is in folder "foo1", the other in folder "foo2". Although named the same to LabView, we will call them foo1 and foo2.- Each XControl directory has a wrapper VI called "foo.vi" which puts
out a reference to the XControl it contains. - A VI called
"samefoo.vi", explained below.- A VI called "anyfoo.vi", explained below.- A property wrapper VI called "prop_whoareyou.vi". This is used by anyfoo.vi and is explained below.

The XControls

The XControls called "foo" each have a label. In foo1, the label reads "This is foo1"; in foo2, the label reads "This is foo2".

Each "foo" also has a property called "whoareyou". This property is
read-only and returns a string. In foo1, the string is "foo1"; in foo2,
the string is "foo2".

samefoo.vi

samefoo.vi loads the wrapper VI of your choice into a subpanel. The
wrapper VI contains the XControl and outputs a reference to it. We
downcast this reference to the type of the "foo" XControl.  Normally we
would use this reference to invoke properties etc., but here we don't
do anything with it, so that we can demonstrate the evil side-effect of
a class type specifier. More on that in a bit.

When you run samefoo.vi, it presents a file dialog. Select one of the
wrapper VIs -- either foo1\foo.vi or foo2\foo.vi. (If you choose a
different one, you will get a type mismatch error.)

Now, we would like foo1\foo.vi to load foo1, and foo2\foo.vi to
load foo2, but that's not what happens. Instead, both wrapper VIs give
us foo1. It doesn't matter which one we load first: we always get foo1.

Why? We're not positive, but we're pretty sure that the culprit is the
class type constant. This causes LabView to store some kind of
reference to an actual XControl (rather like a static VI reference). In
this case, I used foo1 to get the class name, so that's the one that
samefoo.vi is eternally stuck with.

anyfoo.vi

As the name implies, "anyfoo.vi" is our solution to the "samefoo.vi"
problem. Like samefoo.vi, it has a subpanel and loads a wrapper VI into
it. Unlike samefoo.vi, it will load either foo1 or foo2, depending on
the wrapper you choose. It can also call the "whoareyou"
property on either foo1 or foo2 and get the correct result.

anyfoo.vi does this by not including a class type constant or a
property node (the latter has the same pernicious effect). Instead, it
uses the class type constant and property node in prop_whoareyou.vi.
That VI's purpose is to call a property on an XControl in a wrapper VI.
It takes as input a reference to the wrapper VI, calls the promised
property, and outputs the result.

Note that the prop_whoareyou.vi is dynamically loaded. We can't
use the VI itself, because that would cause anyfoo.vi to be stuck with
a reference to foo1 or foo2. We can't use a static reference for the
same reason.

The key is load order. anyfoo.vi loads first, when we open it. It has
no references to XControls, so no XControls get loaded. When we run
anyfoo.vi, it loads one of the wrapper VIs first. This loads the
XControl we want. After that, we load the property wrapper VI. There
only needs to be one of these, because even though the property wrapper
VI has references to one of the foo XControls, it will always use the
foo that's already in memory.

Therefore, it's critical to load the wrapper VI before the
property wrapper VI. Otherwise, either of the foos will load, we won't
be able to choose which one, and it will be stuck in memory until the
property wrapper VI is unloaded.

The verdict

Apparently we can get the effect we want, but we have to resort to evil
chicken-wire-and-chewing-gum trickses, and the process is very
inefficient. But it's the best we can think of. If anybody knows of a
better or more efficient method, we'd love to hear about it.

And NI -- if you we
.



Relevant Pages

  • Re: COM object related question
    ... The trick is knowing just how many times to call ReleaseComObject. ... A VB .NET client connects to one of our connection points. ... events that were implemented did not store any reference to the object passed ... the .NET wrapper object passed in had absolutely no reference to ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Change the name of an component at runtime
    ... compile time are done by reference and would not change. ... negative effect on other forms you might load after that if they refer ... property to lookup pointers and expect to find the named component. ... Why do you need to rename a component at runtime anyways? ...
    (borland.public.delphi.thirdpartytools.general)
  • Accessing Members of Dynamically Loaded Assemblies
    ... I plan to load an assembly during application startup, ... runtime reference to that dynamically loaded assembly? ... the current app domain before going to the assembly manifest to try to load ... then goes through the normal probing ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: No Current Record
    ... If you load the northwind or any other database, ... I did add a reference to his app but that ...
    (comp.databases.ms-access)
  • Referencing Images...
    ... I need to be able to reference some images stored in my VB.NET program. ... I would load the images into an ImageList control and use ... (i.e. in the program I would allows my main database records to 'store' ...
    (microsoft.public.dotnet.languages.vb)

Loading