我需要在运行时加载的程序集中执行一个方法。现在我想在方法调用后卸载已加载的程序集。我知道我需要一个新的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种情况。
如果我设置事件处理程序,会出现找不到/加载程序集(它是管理控制台(mmc.exe)的SnapIn)的异常。
ExecuteAssembly找不到入口点(实际上没有入口点)。
我不知道类型的名称。如何按接口加载?
与3类似。如何获取程序集的名称?
与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...
}
}
这个也不行。在尝试创建代理对象时,我遇到了异常:
无法加载文件或程序集'MyProject.SnapIn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'或其某一个依赖项。系统找不到指定的文件。错误信息中提到的文件是加载到mmc中的文件(SnapIn)。有任何想法如何修复此错误吗?AppDomain.AssemblyResolve没有被调用(旧域和新域都没有被调用)。
更新2
现在我已经尝试了使用AppDomainSetup的解决方案。现在,异常信息已经变成了:
无法加载文件或程序集“file:///C:/Development/MyProject/bin/SnapIn/MyProject.SnapIn.DLL”或其某一个依赖项。给定的程序集名称或代码库无效。(来自HRESULT的异常:0x80131047)有任何想法吗?