I need to implement a plugin architecture within c#/.net in order to load
custom user defined actions
data type handling code for a custom data grid / conversion / ...
from non-static linked assembly files.
Because the application has to handle many custom user defined actions, Iam in need for unloading them once executed in order to reduce memory usage.
I found several good articles about plugin architectures, eg:
ExtensionManager
PluginArchitecture
...
but none of them gave me enough sausage for properly unloading an assembly.
As the program is to be distributed and the user defined actions are (as the name states) user defined: how to i prevent the assembly from executing malicious code (eg. closing my progra, deleting files)?
Are there any other pitfalls one of you has encountered?
Have you thought about using the Add-Ins and Extensiblity framework from MS?
http://msdn.microsoft.com/en-us/magazine/cc163476.aspx
Michael
One technique is to load the additional assemblies into a separate AppDomain. Unloading the AppDomain will unload the assemblies.
You can't unload a single assembly. You can only unload a group of assemblies by unloading the AppDomain they are a part of.
This is essentially how SQL CLR works, and ASP.NET -- by having a transient AppDomain for user-supplied assemblies.
Related
I'm beating my head against the wall trying to find a container that will accomplish this.
What I'd like to do is have a AS.NET website running and not unload / recycle the AppDomain when I deploy a new or updated business rule contained in an assembly. This implies that the folder is outside of the bin folder, and preferably above it, not under it (although I can live with that). The closet I've come to this so far is using Autofac and MEF, but it seems like there's no way to unload a previously loaded assembly.
Anybody have any resources they can point me to?
Thank you,
Stephen
No, there is not. Because it is not possible to unload an assembly, only a total appdomain. THis is a .NET runtime limitation - and as every .NET IOC container has to live in the .NET runtime it can not bypass it.
If your imports are big enough isolating them in separate appdomains may be a good and viable idea.
You can not unload assemblies in .Net without unload whole AppDomain. So the only way to allow it is to load new assemblies into new AppDomains.
While it may be possible to build such IoC container that will marshal all requests to new AppDomains for many interfaces such code would put very significant restrictions on methods/objects exposed by the interfaces. Also many .Net objects can't cross AppDomain boundary (xml, UI/controls, HTML context, database related classes).
It is significantly easier to allow ASP.Net to deal with reloading of the AppDomain.
Is there a way to indicate to the CLR to load an class library assembly as domain neutral?
The use case is MSCRM plugins in which each plugin is loaded in a separate app domain and needs the services of a "utility" library which can be quite large (10+ megs) and it would be neat to be able to load a single copy of the code page that is shared across all app domains, thus reducing the memory footprint of the overall process
You can load a assembly as domain neutral, you need apply the attribute LoaderOptimization as MultiDomain. Check this article to know how do that.
I have a web application that dynamically loads assemblies based on database configuration entries to perform certain actions (dynamic plugin style architecture).
The calls to the objects are in a Factory Pattern implementation, and the object is cached (in a static dictionary<> within the Factory) as the calls can be made many thousands of times in a minute.
The calls to this factory are made from both the main web application and a number of webservices, some in different assemblies/projects.
When I need to update one of these DLLs, I have to recycle IIS to get the DLL released.
As this has an impact on another application on the server, I wanted to know if there was a way I could release the DLL without restarting IIS?
There's absolutely no way to unload a loaded assembly other than killing the AppDomain which is basically what you are doing when you restart IIS.
You can try restarting the application pool not the whole IIS server. Maybe that will do the trick for you
If you have an assembly that you need to load and unload you will have to jump through a few hoops.
the types being loaded must derive from MarshalByRefObject
the types being loaded must derive from an interface that will be used to call them
you must build a remoting based 'loader' to isolate the loaded assembly in a new appdomain, which can be unloaded.
see http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm for a good introduction. It is a bit dated and deals with dynamically generated code but given your rep I would assume that you can extract the relevant information.
What are some guidelines and best practices for when to create new application domains within an application?
Also, what are some common uses and examples of how multiple application domains are used whithin an application?
The most common scenario I've seen is to be able to provide extensibility with a different security model than the main program.
Loading a plugin in a separate AppDomain allows two things:
You can implement a more restricted security model
You can prevent the plugin from tearing down your application if it's buggy
Another nice use of AppDomains are to load and inspect an assembly. Doing this in a separate AppDomain allows you to glean information (or run code) from a separate assembly, then unload the entire assembly from your process's space. If you load the assembly directly, there is no way to unload it. This is also useful if you want to be able to, at runtime, "upgrade" a type to a new version (ie: load a remote assembly, and reload it later).
It is recommended to create new domain when you need to host 3-rd party components within your application that are unreliable or you do not trust them (like plug-ins) or you want to be able to unload them.
A typical example is for plugin-/addin-like cases. Not only does it allow you to unload the DLL if required, it also gives you better security control over what the plugin is allowed to do.
Also, if you create temporary assemblies (code generation) which you want to unload again, this is a good way to do it. (LCG only allows implementing single methods, if you want to implement a complete class you need to emit to a "real" assembly).
My project is an application in which we load various assemblies and perform operations on them.
We are stuck at a situation where we need to add a reference to the assembly we load (which will be selected by user). So I need to add a reference to the DLL at run time.
I tried this site but here they support only microsoft DLLs like System.Security etc. I want to add a reference to a user created dll (class library).
You can't "add a reference" at runtime - but you can load assemblies - Assembly.LoadFrom / Assembly.LoadFile etc. The problem is that you can't unload them unless you use AppDomains. Once you have an Assembly, you can use assemblyInstance.GetType(fullyQualifiedTypeName) to create instances via reflection (which you can then cast to known interfaces etc).
For a trivial example:
// just a random dll I have locally...
Assembly asm = Assembly.LoadFile(#"d:\protobuf-net.dll");
Type type = asm.GetType("ProtoBuf.ProtoContractAttribute");
object instance = Activator.CreateInstance(type);
At which point I can either cast instance to a known base-type/interface, or continue to use reflection to manipulate it.
If the assembly is in another location than the current or in the GAC, just use the
AppDomain.CurrentDomain.AssemblyResolve event to deliver the assembly yourself.
If you load an assembly at runtime, it will look for all its dependencies in the current location or the GAC, and load them if found, else error.
The Composite UI Application Block facilitates the design and implementation of your client applications in three areas:
It allows your application to be based on the concept of modules or plug-ins.
It allows developers with shell expertise to build components that hide user interface complexity from the business logic development.
It facilitates development using patterns for loose coupling between modules.
For WPF: Take a look at Prism: patterns & practices Composite Application Guidance for WPF and Silverlight site It does the assembly loading you require and actually uses Unity internally as it's IoC container.
For non WPF: Take a look at Smart Client - Composite UI Application Block
Or alternatively: Try any of the IoC containers like Castle Windsor, autofac, unity, etc.