我正在制作一个插件管理器,它可以与第三方代码交互。我希望这些插件可以在运行时重新加载,并且还可以从这些插件访问第三方代码(在默认的AppDomain中)。
我尝试使用AppDomains,但没有找到一种方法来调用任何方法,而不必包装每个可用的方法/对象。
我研究了几个问题,例如this answer,其中的链接和this answer给出了关于跨AppDomain通信如何工作的一些见解。
由于有了第二个答案,我已经成功为默认AppDomain中要调用的单个方法创建了一个代理类,但这需要我为从插件调用的每个可能的方法调用添加一个。 >
我还尝试使用带有Action作为传递类型的代码,以允许插件传递要在默认AppDomain中执行的某些代码,但是由于各种错误而失败。这是我最后的尝试。
主要应用:
[Serializable]
public sealed class DelegateWrapper<T1>
{
private Action<T1> _someDelegate;
public Action<T1> SomeDelegate
{
get
{
return _someDelegate;
}
set
{
if (value == null)
_someDelegate = null;
else
_someDelegate = new myDelegateWrapper(value).Invoke;
}
}
private sealed class myDelegateWrapper : MarshalByRefObject
{
public void Invoke(T1 input)
{
_delegate(input);
}
private Action<T1> _delegate;
public myDelegateWrapper(Action<T1> dlgt)
{
_delegate = dlgt;
}
}
}
[Serializable]
public sealed class P
{
public Action Action { get; }
public P(Action action)
{
this.Action = action;
}
}
private static readonly DelegateWrapper<P> PerformWrapper=new DelegateWrapper<P>();
public static void Init()
{
PerformWrapper.SomeDelegate = p => p.Action();
}
在新的AppDomain中,Perform方法正在调用perform.SomeDelegate。
插件(也在新的AppDomain中执行):
Perform(new P(() =>
{
//Third-party code
}));
这导致一个异常,说明它找不到我在插件AppDomain中手动加载的插件程序集。我认为它也在尝试将其加载到默认域中。有办法解决吗?
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Plugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies
此处有完整的堆栈跟踪:https://pastebin.com/xZV7bXeV