inter-AppDomain通信和接口

时间:2013-09-12 18:42:45

标签: c# interface marshalling appdomain

我正在寻找一种方法来隔离可以卸载的单独AppDomain中的组件(基于第三方dll)。我的计划是使用基于CreateInstanceAndUnwrapMarshalByRefObject的对象与组件进行通信。

问题是,为了在主程序集中使用从MarshalByRefObject派生的对象,它必须引用组件dll,我试图避免这种情况。我以为我可以通过界面解耦它

class MyObject: MarshalByRefObject, IMyObject
{
}

但是我无法将从CreateInstanceAndUnwrap返回的对象强制转换为IMyObject(因为它实际上是代理,而不是真正的对象?)。

我错过了什么,或者这是不能完成的,唯一的答案是WCF?

更新: 我遇到的实际问题是IMyObject被定义了两次:我将文件包含在主程序集和组件程序集中。这样我得到一个异常“无法将透明代理强制转换为类型”。当我只使用我从两个程序集引用的一个接口/类定义时,它工作正常(无论是建议还是如上所述)。

1 个答案:

答案 0 :(得分:2)

呃,无论如何,界面有点糟糕。

抛弃它并使用继承自MBRO的抽象基类。

public abstract class MyObject : MarshalByRefObject
{
    protected MyObject() : base() {}
    public abstract void LoadPluginAssemblyLol();
    public abstract void ExecuteSuperCollider();
}

将其拉回边界并以此方式控制插件。此外,请记住不要在类型上公开事件(事件订阅者在没有意识到的情况下被跨越边界)并且您应该只接受方法参数并且返回值是基元或严格控制,以便您不会意外地结束在您的主域中加载的DLL。

您将遇到的另一个问题是,您必须通过 ISponsor 实施来管理代理的生命周期。否则,主机域中的实例将在10分钟后收集。

至于使用MyObject,你会......

//假设一个实现,例如'class MyObjectImplementation:MyObject {...}'

var type = typeof(MyObjectImplementation);
var newDomain = CreateNewAppDomainKthx();
var controller = newDomain
    .CreateInstanceAndUnwrap(
        type.Assembly.FullName, 
        type.FullName) as MyObjectImplementation;
controller.LoadPluginAssemblyLol();
controller.ExecuteSuperCollider();