在不同的AppDomain中加载/卸载程序集

我需要在运行时加载的程序集中执行一个方法。 现在我想在方法调用后卸载那些已加载的程序集。 我知道我需要一个新的AppDomain,所以我可以卸载库。 但在这里,出现了问题。

要加载的程序集是我的插件框架中的插件。 他们根本没有切入点。 我所知道的是它们包含一些实现给定接口的类型。 旧的非AppDomain代码看起来像这样(稍微缩短):

try { string path = Path.GetFullPath("C:\library.dll"); AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; Assembly asm = Assembly.LoadFrom(path); Type[] types = asm.GetExportedTypes(); foreach (Type t in types) { if ((t.GetInterface("IStarter") != null) && !t.IsAbstract) { object tempObj = Activator.CreateInstance(t); MethodInfo info = t.GetMethod("GetParameters"); if (info != null) { return info.Invoke(tempObj, null) as string; } } } } catch (Exception ex) { MessageBox.Show(String.Format("Damn '{0}'.", ex.Message), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); } private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { if (args.Name.StartsWith("MyProject.View,")) { string path = Path.GetFullPath("C:\view.dll")); return Assembly.LoadFrom(path); } return null; } 

现在我希望它们加载到自己的AppDomain中:

 try { string path = Path.GetFullPath("C:\library.dll"); AppDomain domain = AppDomain.CreateDomain("TempDomain"); domain.AssemblyResolve += CurrentDomain_AssemblyResolve; // 1. Exception here!! domain.ExecuteAssembly(path); // 2. Exception here!! domain.CreateInstanceFrom(...); // 3. I have NO clue, how the type is named. domain.Load(...); // 4. I have NO clue, how the assembly is named. domain.DoCallBack(...); // 5. Exception here!! // ... } catch (Exception ex) { MessageBox.Show(String.Format("Damn '{0}'.", ex.Message), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); } 

如你所见,我已经提出了5个案例。

  1. 如果我设置事件处理程序,我得到一个exception,无法找到/加载程序集(它是管理控制台(mmc.exe)SnapIn。

  2. ExecuteAssembly没有找到入口点(好吧,没有入口点)。

  3. 我不知道该类型是如何命名的。 如何通过界面加载?

  4. 类似于3.如何获取程序集的名称?

  5. 与1中的错误相同。

我认为问题可能是管理控制台,或者我不知道我做错了什么。 任何帮助表示赞赏。

更新1

我现在尝试使用发布的代理解决方案。

 AppDomain domain = AppDomain.CreateDomain("TempDomain"); InstanceProxy proxy = domain.CreateInstanceAndUnwrap(Assembly.GetAssembly( typeof(InstanceProxy)).FullName, typeof(InstanceProxy).ToString()) as InstanceProxy; if (proxy != null) { proxy.LoadAssembly(path); } AppDomain.Unload(domain); public class InstanceProxy : MarshalByRefObject { public void LoadAssembly(string path) { AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; Assembly asm = Assembly.LoadFrom(path); Type[] types = asm.GetExportedTypes(); // ...see above... } } 

这也不起作用。 在尝试创建代理对象时,我得到一个exception:

无法加载文件或程序集“MyProject.SnapIn,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null”或其依赖项之一。 该系统找不到指定的文件。

错误消息中的文件是加载到mmc(SnapIn)中的文件。 知道如何修复此错误吗? 不调用AppDomain.AssemblyResolve(在旧域或新域中都不会)。

更新2

我现在尝试使用AppDomainSetup的解决方案。 现在,exception已更改为:

无法加载文件或程序集’file:/// C:/Development/MyProject/bin/SnapIn/MyProject.SnapIn.DLL’或其依赖项之一。 给定的程序集名称或代码库无效。 (HRESULTexception:0x80131047)

任何的想法?

试试这个:

 namespace SeperateAppDomainTest { class Program { static void Main(string[] args) { LoadAssembly(); } public static void LoadAssembly() { string pathToDll = Assembly.GetExecutingAssembly().CodeBase; AppDomainSetup domainSetup = new AppDomainSetup { PrivateBinPath = pathToDll }; var newDomain = AppDomain.CreateDomain("FooBar", null, domainSetup); ProxyClass c = (ProxyClass)(newDomain.CreateInstanceFromAndUnwrap(pathToDll, typeof(ProxyClass).FullName)); Console.WriteLine(c == null); Console.ReadKey(true); } } public class ProxyClass : MarshalByRefObject { } 

请看一下之前的答案: 如何在Windows Mobile(.NET CF)上将程序集加载到不同的AppDomain中? 。 该答案创建了一个代理类,它运行到新的AppDomain上下文中,因此,您可以完全控制您的初始化。

您可以在ServiceApplicationProxy类中创建一个Start()方法,并使用proxy.Start()从您的主机中正常调用它。

https://msdn.microsoft.com/en-us/library/3c4f1xde%28v=vs.110%29.aspx

指定

typeName类型:System.String

 The fully qualified name of the requested type, including the namespace but not the assembly, as returned by the Type.FullName 

属性。

因此尝试使用完全限定名称调用,而不是使用typeof(InstanceProxy).ToString()使用字符串/文本"<>.InstanceProxy"

如下

 InstanceProxy proxy = domain.CreateInstanceAndUnwrap(path, "<>.InstanceProxy") as InstanceProxy;