I am trying to get the hang of Dynamic loading of objects from assemblies on the same machine (But NOT part of the same project).
In the sample below, Form1 implements an interface built as part of the .dll I placed in C:\Release.
I am trying to create a local instance of Form1, and Cast it as Iform, so that the local code can access the properties and methods exposed by the interface.
The assumption here is that at runtime, local code will have access to the String name of a form, and an interface which is implemented by the form (and is compiled into the .dll as well as the client application), and that is it.
Does this make sense?
When I run this code, I get a exception:
"Unable to cast object of type 'WindowsApplication1.Form1' to type 'WindowsApplication1.Iform'.
Code:
Public Function fApplicationObject() As Iform
Dim sLocation As String = "C:\Release\WindowsApplication1.dll"
Dim sType As String = "WindowsApplication1.Form1"
Dim dAssembly As [Assembly] = [Assembly].LoadFrom(sLocation)
Dim dType As Type = dAssembly.GetType(sType)
Dim dObj As Iform = Activator.CreateInstance(dType)
'The Exception happens HERE:
Dim frm As Iform = dObj
'I also tried several other ways;
'CType, Etc, and I even set a reference to the dll, and tried THIS: Dim frm As WindowsApplication1.Form1 = obj
Return frm
End Function
I seem unable to dynamically load an object from a dll and then utilize an interface to access it's properties and such.
I'm guessing that you're actually declaring two different interfaces in the two different projects. Just because they have the same name and members doesn't make them the same type. Check out the attached solution. Note that the interface is defined in a third assembly that both the other two must reference. Both the application and the library you're loading dynamically must refer to the same interface.
Ha!
Thanks for that. That makes complete sense now, after a good night's sleep!
Would I be correct in assuming that this is where a project can take on a whole new level of complexity, and where all of the Versioning aspects I have been ably to ignore are now going to begin mattering in a big way?
On the one hand, I feel less safe creating a monster project dependent upon external libraries. On the other hand, my project is GOING to be quite complex, and there are several areas in which discrete libraries of shared objects makes sense.
I guess my question to anyone reading this is, should a relative novice venture into this area?
I'm not sure that dynamic loading of assemblies is something you should bother with unless you specifically need it. It's good to know that you can do it and, in a general sense, how but it's not something you'll need all that much. The fact that you're going to have a complex application is certainly reason to break it up into multiple libraries but it doesn't mean that those libraries will need to be loaded dynamically. You should simply break your functionality up into logical chunks and put each one in its own library, but each of those libraries should reference its dependencies directly. Don't load assemblies dynamically unless you have a specific reason to do so. In all the time I've been working with the .NET Framework I haven't had such a reason.
THanks for you feedback. The DemoApplication worked Great,, and I believe I understand things a little better now.
Your time and effot is much appreciated. I will examine how I am structuring this, but what I am trying to get to is the same thing the guy in the link I posted is doing- making the app easily extensible so we can stasrt using it, and add additional functionality as it grows without having to add code to the main app-new objects will be self-contained, and added to the app by making a new record in the SQL Server table set.
Like a true idiot, I didn't start all this with a small, easily finished project in mind, I went for the gusto- The app will ultimately include hundreds of objects or forms (depending on how well I learn to structure these things), so I am trying to come up with a way to use a table in my SQL back-end to manage object names, which are loaded into the app at runtime. I want to initially load a Treeveiw control with some sort of pointer to a collection of objects (also loaded at runtime), yet be able to add a new object by the simple entry of a new record in the back-side table.
I am not explainning this well. Thanks for the help JMC.
In the case that you describe you certainly do have a reason to load assemblies dynamically. You might also want to take a look at the System.AddIn namespace and its child namespaces. They provide a framework for creating an extensible application and the components that extend it.
I gotta run off to work, but I plan to look into what you suggest re: appAddin when I get home!
I should mention that it probably is NOT necessary to load the assemblies themselves at run-time. The app CAN know where to look, and I could set references within the app to the assemlies required.
I was having no luck with run-time object creation that way. However, that was in my sleep-deprived state last nite. Is it safe to assume (until I get home!) that it is possible to accomplish what we resolved above by using .CreateInstance with a referenced assembly? In other words, skip the "LoadAssembly" part, and proceed with the load of the object and necessary interface from a referenced assembly?
Or is that going to be another version of the same thing?
I marked this thread resolved, because you totally answered the topic question. However, any parting thoughts on the above would be GREAT!
You can't reference an assembly without rebuilding your application, so that's something to consider.
I also don't really understand why you'd want to use CreateInstance to create instances of types you have direct references to. The direct reference is pointless in that case. There might be some very special circumstances that would require it but I can't think of any offhand.
I need to reference the specific OBJECT within an assembly dynamically. The object name (and any other information needed to create it) can be retreived from the SQL back-end as String information (or numeric, or what have you).
I am trying to avoid a scenario where every time a new form is added to a list of potential forms one might navigate to from a treview, one then has to go code for the addition to either the treeview or other such control which needs to point to the form.
Unless it is possible to somehow, at load, iterate through all of the objects within a certain assembly, and load those which either have a certain prefix or suffix (or even better, implement a certain interface) and load them into a collection. Of course, in that case, I THINK I would end up with a collection of what amounts to single instances, almost like "deault" instances (which I hate), instead of a fresh instance each time the user sleected a certain tree node from the list.
Does that make sense?
I am having trouble explaining this, but an example might be the "add user" pop-up within SQL Server management studio. To the left is a treeview. To the right, panels are loaded depending upon which Treenode is selected. In MY case, I want to be able to add a new panel at some later point, which may have totsally different conrtrols. The panel would be built within an external assembly, and implement a common interface which the container form would recognize.
At Load, the container form would retreive a collection of values from a table in SQL Serve corresponding to the panel items it should load, and place them (or pointers to the objects created from them) into the TreeNode (possibly in the "Tag" property). This way, the Host form will NOT know until runtime what menu items to list; therefore, the object (form) to be shown for each Tree Item has to be retrieved dynamically. If the external .dll needed to be re-compiled after the addition, or a new reference set after a new Form is added, fine. Right?
Last edited by RunsWithScissors; Jul 9th, 2009 at 01:07 PM.