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

Sco*_*hic 22 c# reflection mmc 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;
}
Run Code Online (Sandbox Code Playgroud)

现在我希望它们加载到自己的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);
}
Run Code Online (Sandbox Code Playgroud)

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

  1. 如果我设置事件处理程序,我得到一个异常,无法找到/加载程序集(它是管理控制台(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...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

无法加载文件或程序集"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)

任何的想法?

BFr*_*ree 14

试试这个:

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 { }
Run Code Online (Sandbox Code Playgroud)