我可以从另一个AppDomain将类型实例化为“动态”吗?

时间:2012-06-26 18:40:26

标签: c# dynamic appdomain

我正在尝试将来自不同程序集(在构建时不知道)的类型加载为“动态”并在该类型上执行方法。我的目标是完全断开'插件'与父应用程序的连接,这样就不需要任何共享代码或通用接口类型。通过加载类型上的预期方法签名来暗示接口。

这有效:

dynamic myObj = Assembly.Load("MyAssembly").CreateInstance("MyType");
myObj.Execute();

但是,这会将类型加载到当前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);

这基本上是我的目标案例,我一直试图让这样的事情发挥作用:

dynamic myObj = ad.CreateInstanceAndUnwrap(assembly, type);
myObj.Execute();

我一直以RuntimeBinderException结尾,消息“'System.MarshalByRefObject'不包含'Execute'的定义”。这条消息有意义,确定它不包含'Execute'的定义,但我知道我实例化的类型确实包含'Execute'方法。我想这里有一些透明代理正在阻止它工作,但我不确定是什么。

我尝试实例化的实际课程如下:

[Serializable]
public class MyClass : MarshalByRefObject {
  public void Execute() {
    // do something
  }
}

我也尝试过这个共享界面(不是我的主要目标,但我想先弄清楚这个)所以它看起来像:

[Serializable]
public class MyClass : MarshalByRefObject, IPlugin {
  public void Execute() {
    // do something
  }
}

其中IPlugin是父应用程序中的已知类型,并且插件在构建时具有适当的引用,但这似乎也不起作用。

我猜在这一点上,不可能在AppDomain边界上加载一个动态类型。

有没有办法让它真正起作用?

1 个答案:

答案 0 :(得分:5)

作为leppie indicated,您必须实施IDynamicMetaObjectProvider interface以包装要返回给您的代理,然后您可以使用make dynamic来电在

在您的实施中,您希望获取已包装的代理并将所有调用转发到ExecuteMessage method上的静态RemotingServices class,这将占用您的代理,以及{{{ 3}}实施。

请注意,实现IMethodCallMessage接口并非易事。此外,您必须正确解释IMethodCallMessage interface实施,以正确获取返回值,refout参数(如果有)。

也就是说,提供一个仅包含 接口的程序集通常是一个更好的主意,供客户端和服务器承担;如果在服务器端以任何方式更改方法,即使客户端使用dynamic,您仍然 仍需要更改呼叫站点以适应更改。至少使用接口,您可以获得某种类型的编译时检查,这始终是运行时错误的首选。