How do I implement .net plugins without using AppDomains?

断了今生、忘了曾经 提交于 2019-11-27 20:19:30
  1. Check if the assembly is already loaded (to avoid memory leaks caused by loading the same assembly over and over again).
  2. If its not loaded, read the assembly into a byte array. This will prevent locking the file.
  3. Supply the byte array as an arguement to Assembly.Load

The following code assumes you know the FullName of an assembly.

Assembly assembly = null;

foreach(Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies())
    if (loadedAssembly.FullName == "foobar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
        assembly = loadedAssembly;

if(assembly == null)
{
    byte[] studybin = System.IO.File.ReadAllBytes(@"C:\pathToAssembly\foobar.dll");
    assembly = Assembly.Load(studybin);                
}

Note that if you are trying to find a specific assembly in a directory, you can run 'System.Reflection.AssemblyName.GetAssemblyName(path);' to see if the FullName matches what you are looking for. 'GetAssemblyName(path)' does NOT inject the assembly into your current AppDomain.

Also note that this solution is not appropriate for applications that must only rarely restart AND the assemblies change with high frequency. Every time an assembly is loaded, the memory footprint of you application will grow. There is no method to unload an assembly, thus the only option to shrink memory usage is to restart the application. However, this limitation is often preferable to the large performance, memory, and code complexity overhead of using multiple app domains. This limitation is also unavoidable if you wish to work with Types.

If you want to isolate your addins, you must...

  1. Create a type that extends MarshallByRefObject which will interact with your addins (lets call it FOOMASTER)
  2. Create a new appdomain (lets call it addinLand)
  3. Call addinLand.CreateInstanceAndUnwrap to create an instance of FOOMASTER in addinLand and get a proxy in the current app domain
  4. Tell FOOMASTER to load your addins

Now your addins are loaded in addinLand and you can interact with them from your primary appdomain via your FOOMASTER proxy. When your addins crash, they don't take down your application.

Its an interesting and slightly confusing process. I originally thought the idea was to load your addins and then bring them over into the current app domain as transparent proxies, but the best design is to leave the addins as simple objects that interact with more complex types you create (FOOMASTER), that extend MarshallByRefObject, that are loaded in the addinLand app domain, and whose transparent proxies you interact with.

Chapters 21 and 22 of CLR Via C# are very helpful in understanding the process.

If you are interested in a serious method for building a system with a plugin architecture, you might want to check out MAF (Managed Add-in Framework), which is now part of the .NET Framework, namely the System.AddIn namespace.

It will help you manage add-in isolation and versioning, even backward compatibility with contracts.

There is a bit of a learning curve here though, so this may not be exactly what you are looking for.

http://msdn.microsoft.com/en-us/library/bb384200.aspx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!