C#AppDomain无法加载DLL

时间:2016-07-21 13:52:28

标签: c# dll plugins appdomain

我正在尝试构建一个热插拔插件系统,用户可以动态加载和卸载dll。核心应用程序尽可能少地重新启动是必要的,因此我将尽可能多的功能转移到外部库。根据我已经发现的研究,我需要创建第二个AppDomain并将DLL加载到其中,然后只需将参数传递给它以运行它。目前,我相信我的大部分程序都在工作,但是当我从CreateInstance调用对象的AppDomain.Unwrap()函数时遇到错误。错误如下:

System.InvalidCastException: Unable to cast transparent proxy to type 'Program1.Loader'.

这是加载代码:

try {
    unload(dom,out loader,true);
    dom=null;
    AppDomainSetup dms = new AppDomainSetup();
    dms.ConfigurationFile=Environment.CurrentDirectory+Path.DirectorySeparatorChar+"Program1.exe.config";
    dms.ApplicationBase=Environment.CurrentDirectory+Path.DirectorySeparatorChar+"Plugins";
    Evidence ev = AppDomain.CurrentDomain.Evidence;
    dom=AppDomain.CreateDomain("PluginManager",ev,dms);
    AssemblyName an = AssemblyName.GetAssemblyName(Environment.CurrentDirectory+"\\Plugins\\PluginManager.dll");

    ObjectHandle obj = dom.CreateInstance(an.FullName,"PluginManager.PluginManager");
    loader = (Loader)obj.Unwrap();
    loader.LoadAssembly(@"PluginManager.dll");

    if(!suppressOutput)
      Console.WriteLine("Reload successful.");
  }
  catch(Exception e) {
    unload(dom,out loader,true);
    loader=null;
    Console.WriteLine("PluginManager failed loading. Enter \"reload\" to try again.\n");
    Console.Write(e+"\n\n");
  }

此行是引发错误的地方:

loader = (Loader)obj.Unwrap();

外部DLL几乎没有代码,因为这是一个概念证明。它如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PluginManager {
  public class PluginManager:MarshalByRefObject {
    public void run(string comm) {
      Console.WriteLine(comm);
    }
  }
}

编辑:这里是加载程序类的代码。

  class Loader:MarshalByRefObject {
    private Assembly _assembly;

    public override object InitializeLifetimeService() {
      return null;
    }

    public void LoadAssembly(string path) {
      _assembly=Assembly.Load(AssemblyName.GetAssemblyName(path));
    }

    public object ExecuteStaticMethod(string typeName,string methodName,params object[] parameters) {
      Type type = _assembly.GetType(typeName);
      MethodInfo method = type.GetMethod(methodName,BindingFlags.Static|BindingFlags.Public);
      return method.Invoke(null,parameters);
    }
  }

1 个答案:

答案 0 :(得分:0)

您似乎正在尝试在PluginManager中创建AppDomain类型的对象,然后将其代理转换为类型Loader(您的代码丢失了)代码示例)。

问题在于以下几点:

ObjectHandle obj = dom.CreateInstance(an.FullName,"PluginManager.PluginManager");
loader = (Loader)obj.Unwrap();

如果你要么创建Loader而不是PluginManager的实例 - 或者 - 转换为PluginManager而不是Loader,那么它会起作用。我的猜测是前者:

ObjectHandle obj = dom.CreateInstance(an.FullName,"LoaderNamespace.Loader");

(将LoaderNamespace替换为真实的。{/ p>