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.
Related
I am trying to make a C++/MFC application (so called "Update Application") that can extract AssemblyVersion information from other applications written in C#/.NET 3.5.
So I can update my C# program according to the version information I can get.
I am pretty sure this is possible, but I don't know which way would be the best way.
I would like to know some techniques or keywords that I can search on the web.
A direct explanation would be appreciated, too.
Here's roughly how we do something similar in a native C++ app.
Compile with /clr. You can do this project-wide or just on selected C++ files, but as far as I remember there were complications doing it selectively and so we just did it project-wide. Also #include <vcclr.h> wherever appropriate.
You'll need to learn about app domains. The main thing here is that once you've loaded an assembly into a domain, you can't unload the assembly except by unloading the entire domain. Since you want to load an assembly, query its version, and then let it go, you'll probably want to create a temporary domain and load into this.
In our system we have a managed C++ class called ModelLoader to load object models, query their version info, and discard them - just like what you want to do. This class is the pivotal element in our managed/unmanaged marshaling.
The code in the ModelLoader has to execute in the temporary domain, because we want it to load the target assemblies there and then unload the domain However, the main app is already running in the main domain and so it needs to be able to marshal method calls across to the ModelLoader in the temp domain. So ModelLoader inherits System::MarshalByRefObject, which allows the .NET runtime to do all the marshaling magic.
So the basic steps are something like this:
Load the assembly that contains the code for ModelLoader. In our system this is built into our main unmanaged .EXE and so we just use Reflection::Assembly::GetExecutingAssembly() to get a handle to it. If your equivalent of ModelLoader is in a separate assembly then you'll have to load it somehow. But since you probably won't need to unload this assembly you can load it into the main domain.
Create a temporary domain.
Create an instance of your ModelLoader class (obviously it will have a different name in your system) within the temporary domain.
Marshal a handle to that new instance back to your main domain.
Use the marshaled handle from within your main domain to execute code in the temp domain.
Unload the temporary domain.
So, in code:
AppDomain ^domain = AppDomain::CreateDomain(L"temp domain");
Assembly ^assembly = Assembly::GetExecutingAssembly();
ObjectHandle ^handle = domain->CreateInstanceFrom(
assembly->Location,L"ModeLoader");
Object ^o = handle->Unwrap();
ModelLoader ^loader = dynamic_cast<ModelLoader^>(o);
loader->GetAssemblyVersion(...);
AppDomain::Unload(domain);
To save you some head-scratching, the namespaces involved are:
System::AppDomain
System::Reflection::Assembly
System::Runtime::Remoting::ObjectHandle
System::Object
Within your ModelLoader, you'll want to load the target assembly and query its version info. Compared to all the other stuff, this is straightforward:
void ModelLoader::GetAssemblyVersion(const wchar_t *filename, AssemblyName ^name)
{
Assembly ^assembly = Assembly::Load(gcnew String(filename));
name = assembly->GetName();
}
(I made this function up just now, so it might not be quite right.)
Another thing to watch out for is assembly resolution. This is how the assembly loader resolves assembly names to DLL files. This is quite a large field in its own right, so I won't talk any more about it right now. (And in any case I'm no expert.) To get started, just make sure that all the assemblies you want to load are in your main app directory and I think you'll be more or less OK. Then when you have the basic loading working, you can worry about more sophisticated resolution.
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.
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.