我正在尝试构建一个热插拔插件系统,用户可以动态加载和卸载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);
}
}
答案 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>