I'm a bit lost with MEF, MAF, Unity ...
This question is about architecture of Winform application.
I've got a main project which contains a Main form and some other forms;
Because i want to include modularity, i'm thinking of using a Plugin System.
What I would like to do is opening each Plugin Dll when the Main Application is opened to reference each with button, toolbar ...
Then i would like to dispose them until they are called.
But i don't want all the plugins to be kept in memory.. just to got a good architecture model.
So first about .NET :
Does dotNet keep only a reference to the dll plugins in memory or all the plugin code ?
I'm thinking of using MEF with LAZY collection of Import, but i need to instantiate them first to get my buttons informations. So second question
If i set the Import Collection to null and lauch the compose() function again, the plugins will be load or wait until call to be load (lazy) ?
Then i would like to dispose them until they are called.
Instead of inspecting imported objects and then throwing them away, you should inspect the import metadata. You can get this metadata by importing Lazy<IFoo,IFooMetadata> or Lazy<IFoo,Dictionary<string,object>>. You can add this metadata to exports with the ExportMetadata attribute.
So first about .NET : Does dotNet keep only a reference to the dll plugins in memory or all the plugin code ?
Once an assembly is loaded it remains in memory, unless you unload the whole AppDomain.
Also, there are no out-of-the-box implementations of ComposablePartCatalog in .NET 4.0 which can be queried without loading the corresponding assembly. But in theory something like that could be done if you store the metadata somewhere outside the assembly. There is a sample of such an implementation in the MEF code on codeplex.
I'm thinking of using MEF with LAZY collection of Import
Using lazy imports will not necessarily prevent assemblies from being loaded. If you have a reference to a Lazy<IFoo> object, then at least the assembly containing IFoo has to be loaded. And as I explained above, the assembly containing the exported IFoo implementation will also have been loaded at that point.
Using Lazy will only postpone the invocation of some constructors, hopefully resulting in faster start-up of your application.
Related
I have complex .NET class library is dependent on several other .NET class libraries, but not all of them are used in every situation. Is there any way to mark them as 'Lazy loading', so I can delete it from folder if I know it is not used at all?
All assemblies are always loaded on demand. If you remove an assembly from a folder, the application will work until the point where it needs to load that assembly.
I have ocx created in VC++ If it is loaded statically it works fine but when I load it dynamically from assembly it gives exception .
public Assembly assembly;
public Form1()
{
InitializeComponent();
assembly = Assembly.LoadFile(Application.StartupPath + "\\abc.ocx");
}
it gives following exception The module was expected to contain an assembly manifest.
(Exception from HRESULT: 0x80131018)
You'll have to perform a number of steps that are normally taken of automatically when you use the toolbox. First and foremost, you have to run the Aximp.exe utility to generate the .NET interop assemblies. Use the Visual Studio Command Prompt to run the tool. You'll get two assemblies, axinterop.foo.dll contains a wrapper class that's derived from AxHost and allows you to put the control on a form. And interop.foo.dll, the interop assembly that makes the COM interfaces implemented by the control callable from a .NET program.
Next you have to ensure these DLLs are present in the build directory. Best thing to do is to add them to your project and set their Copy to Output Directory to "Copy if newer".
Now you can use Assembly.Load("axinterop.foo.dll") in your code to dynamically load the interop assembly.
Next you have to create an instance of the control, use Assembly.CreateInstance() and pass the type name of the AxHost wrapper class. If you have no idea what its name might be, it isn't obvious, then use ildasm.exe to look at the axinterop.foo.dll assembly. Cast the returned object to AxHost.
Next you have to add the control to the form's Controls collection so it is visible and usable. You cannot call any interface methods until the control instance is created, that doesn't happen until you've added the control and the form's Load event has fired.
Next you have to use reflection or the dynamic keyword to obtain a reference to the interfaces implemented by the control, in case you need to set properties or call methods. That's difficult to get right, you'll want to write that code first with the control added from the toolbox so you don't have to guess too hard at the proper names.
This is obviously all quite painful and hard to get right. Improve the odds for a good outcome by adding a class library to your project that uses the OCX directly and exposes its important properties through an interface. And use Assembly.Load() on that one.
Assembly.LoadFile can only load .Net assemblies not native dll/exe/ocx files.
You can add a reference to the ocx file via Solution Explorer-->References and then create an instance of the ocx class.
What's the point of dynamically loading an assembly? Isn't it just way simpler to just reference it in your solution/project, saving you all the calls to Assembly.*Load* functions?
Update: Is it useful outside of plugins? What about exclusively in web development, what uses would I find there for dynamically loading an assembly?
Dynamically loading an assembly is useful for anything requiring execution of external code that might not even exist when the hosting program is developed.
For instance, any plug-in system will have to use that feature.
What if you want to make it possible to write plugins for your application, which get loaded at runtime and you don't have that project at compiletime?
You may not have that assembly when you compile your code, think of plugins for instance. You can't compile with a reference to them. Other reason is generating and compiling code and then loadin that Advanced stuff but real use.
GJ
I am developing a windows 7 gadget.I am creating an activex object and loading the assembly.I am following the methodlogy mentioned here at codeproject (GadgetInterop). One of the tasks of the gadget is to interface with Facebook.
This is how I am referencing:
Javascript creates a GadgetBuilder object.
From here I load the my library. say "MyLibrary.dll".
When I call method say MyLibrary.GetCount(), (just return some integer) it works.
But when I call some facebook function inside the method say MyLibrary.GetFaceBookFeeds() it throws an error.I reference "facebook.dll" from CodePlex
If I test my code from a ASP.NET form it works perfectly. However, When I run it from my html page by trying to load it using javascript, I get the following error:
Could not load file or assembly 'facebook, Version=2.1.3654.38113, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
I verified that the dll's are in the same folder as "MyLibrary.dll".
Why is this error coming?
How do I go about achieving my task? (I need to use calling a dll from javascript as we are doing a lot of other things in the dll).
You're not forced to use a reflection-based assembly loader for .net code in desktop gadgets, you can write the assembly to be com visible, using class ids, etc. This article provides an example of using .net to achieve what you're trying to do without the "adapter".
That being said, there are various problems with activex based desktop gadgets that you should be aware of:
When an ActiveX instance is created in the gadget, the assembly dll will be "locked open" by sidebar.exe and the file cannot be deleted, even after the gadget has been closed. Unfortunately the gadget uninstallation process doesn't account for this and an uninstallation of the gadget will result in sidebar.exe copping out of the file deletion when it fails to delete the assembly, leaving the assembly and any other remaining files that hadn't been deleted up to that point. There's also no error message displayed. The same is true of overwriting a gadget (with a new version, for instance) - sidebar.exe attempts to delete the folder completely before installing the new gadget package, resulting in a failed installation in most cases.
The registration of such an activex control can be very tricky. The registry script given in the CodeProject article you provided does not work on my Windows 7 x64, for instance. The only way to work around this is to use WMI to write to the registry.
In a similar fashion, unregistration of the ActiveX control is also an issue. When the user uninstalls the gadget, the registry entries are left behind. Not a problem for a lot of people I suppose, but imagine a gadget enthusiast who tries every gadget he finds suddenly discovering the many unused registry entries. You can get around this by removing the registry entries directly after instantiating the object (since it's cached by the sidebar process anyway) and re-registering it again next startup.
So really although you can do it without reflection, using reflection can be a better option because you can copy the adapter assembly to an alternative folder, use it to load the current assembly and then unload it when the gadget is closed or finished using it. This eliminates the first issue of not being able to uninstall the gadget because the hosting assembly is located in a different folder and the reflected assembly is unloaded when the gadget is closed anyway.
The reason facebook.dll isn't loading is because the loader you're using doesn't correctly resolve dependencies (it can't find the file because it doesn't know where to look). You're welcome to try our reflection-based assembly loader called PluginLoader and see if that works. We haven't had an official release for it yet but we were intending to make it widely available and recommended for use by all developers to try and eliminate the problems with ActiveX and Windows Desktop Gadgets. Because we haven't officially released it you'll have to install our gadget, Auction Sidebar Tool which will install the plugin loader ready for use with the following code:
var plLoader = new ActiveXObject("Sidebar.PluginLoader");
var myLibrary = plLoader.LoadAssembly(classToLoad,
System.Gadget.path+"\\path\\to\\MyLibrary.dll");
myLibrary.GetFaceBookFeeds();
Where class to load is the class you need to load in the format Namespace.Class (ie MyLibrary.MyClass). We specifically coded it to correctly resolve any dependencies so it should work for you just fine. If it does work for you, you're welcome to include it with your gadget. All you need is the PluginLoader.js and PluginLoader.dll files from the AuctionSidebarTool folder, but you'll need to edit the PluginLoader.js file to remove the parts that reference our assembly (line 110 onwards). If you include this in your project, it will check for an existing PluginLoader.dll and if it fails, it will copy it to the Windows Sidebar folder in local AppData, register it and provide the AddInLoader object with the methods LoadAssembly and UnloadAssembly. If you need any extra help just let me know in the comments.
Hope that helps. That's probably the longest answer I've written so far on SO :)
I am running on Windows CE and using the Compact Framework. I need to get a list of all reference assemblies that my application has loaded. It would be nice to be able to get to the AssemblyName (object) of these assemblies.
An example is like getting my running assembly by doing: Assembly.GetExecutingAssembly(); except I need to get the reference to all the other loaded assemblies (3rd party Dlls).
The full framework has the Assembly.GetExecutingAssembly().GetReferencedAssemblies() method but it's not available on the Compact Framework. Any help would be appreciated.
Based on this it would appear that managed dll's are not truly 'loaded' in the sense that they are in the conventional framework. Instead the IL is memory mapped and the JIT just grabs what it needs as it goes along (saving having to maintain a load of memory for code that has executed but is no longer used)
This would explain why the CF provides no way to iterate over the loaded dll's. As to why it doesn't allow iterating over the referenced dlls which are an entirely complie time construct...
As a possible work around:
Use GetExecutingAssembly to get the active code. Ensure that this happens in your executable so it gets the root assembly.
Write some code capable of parsing the dll for the manifest indicating which assemblies are referenced (this need not be managed code - the unmanaged introspection API microsoft provides may even do this for you and the dll format specification is both public and unlikely to radically change in the near future). I suggest black listing dll's loaded from the GAC (though this may be unnecessary).
I guess if there is no API to do this you can try this out ...
Remember, this is not a good way to do this ...
Look for PInvoke calls in Windows CE and call those to figure out what dlls are loaded by the process.
Then iterate through the dlls to check if they have a CLI header. Or you can just try to load the dll as assembly, if it loads then it is a .NET assembly loaded by the application.
I know its not a right way to do this, but this might work.