Chr*_*los 12 c# dynamic appdomain
我正在尝试将来自不同程序集(在构建时不知道)的类型加载为"动态"并在该类型上执行方法.我的目标是完全断开'插件'与父应用程序的连接,这样就不需要任何共享代码或通用接口类型.通过加载类型上的预期方法签名来暗示接口.
这有效:
dynamic myObj = Assembly.Load("MyAssembly").CreateInstance("MyType");
myObj.Execute();
Run Code Online (Sandbox Code Playgroud)
但是,这会将类型加载到当前AppDomain及其所有依赖程序集.我想修改它以允许我在单独的AppDomain中执行相同的操作.
这有效,但没有使用dynamic关键字,我需要知道我实例化的显式类型,以便能够调用Execute方法:
var appDomain = AppDomain.CreateDomain(domainName, evidence, setup);
var myObj = appDomain.CreateInstanceAndUnwrap(assembly, type);
typeof(IMyInterface).InvokeMember("Execute", BindingFlags.InvokeMethod, null, myObj);
Run Code Online (Sandbox Code Playgroud)
这基本上是我的目标案例,我一直试图让这样的工作:
dynamic myObj = ad.CreateInstanceAndUnwrap(assembly, type);
myObj.Execute();
Run Code Online (Sandbox Code Playgroud)
我一直以RuntimeBinderException结束,消息"'System.MarshalByRefObject'不包含'Execute'的定义".这条消息有意义,确定它不包含'Execute'的定义,但我知道我实例化的类型确实包含'Execute'方法.我想这里有一些透明代理正在阻止它工作,但我不确定是什么.
我试图实例化的实际类看起来像这样:
[Serializable]
public class MyClass : MarshalByRefObject {
public void Execute() {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
我也尝试过这个共享接口(不是我的主要目标,但我想先把它弄清楚)所以它看起来像:
[Serializable]
public class MyClass : MarshalByRefObject, IPlugin {
public void Execute() {
// do something
}
}
Run Code Online (Sandbox Code Playgroud)
其中IPlugin是父应用程序中的已知类型,并且插件在构建时具有适当的引用,但这似乎也不起作用.
我猜这一点是不可能在AppDomain边界上加载一个动态类型.
有没有办法让它真正起作用?
作为leppie表示,你必须实现IDynamicMetaObjectProvider接口来包装就是BEING返回给你的代理,然后你可以用make dynamic在电话那.
在您的实现中,您需要获取包装代理并将所有调用转发给类上的静态ExecuteMessage方法,这将占用您的代理以及接口实现.RemotingServicesIMethodCallMessage
请注意,实现IMethodCallMessage接口并非易事.此外,您必须正确解释IMethodReturnMessage接口实现以正确获取返回值ref和out参数(如果有).
也就是说,提供一个仅包含客户端和服务器接口的程序集通常是一个更好的主意; 如果在服务器端以任何方式更改方法,即使客户端使用dynamic,您仍然必须更改调用站点以适应更改.至少在接口上,您可以获得某种类型的编译时检查,它始终优先于运行时错误.