AppDomain 间通信和接口

Posted

技术标签:

【中文标题】AppDomain 间通信和接口【英文标题】:inter-AppDomain communication and interfaces 【发布时间】:2013-09-12 18:42:45 【问题描述】:

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

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

class MyObject: MarshalByRefObject, IMyObject


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

我是否遗漏了什么,或者这无法完成,唯一的答案是 WCF?

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

【问题讨论】:

【参考方案1】:

呃,接口有点烂。

放弃它并使用继承自 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();

【讨论】:

感谢您的提示!我可以这样做,但是如何通过 CreateInstanceAndUnwrap 以某种方式创建 MyObject? 好吧,使用例如类型typeof(MyObjectImplementation) 表示我需要从主程序集中引用该组件。我试过CreateInstanceAndUnwrap(..., "MyObjectImplementation") as MyObject,它似乎工作正常。我发现我的项目存在问题,修复后界面现在也可以正常工作。在我的情况下,ISponsor 应该不是问题,但非常有用,再次感谢。

以上是关于AppDomain 间通信和接口的主要内容,如果未能解决你的问题,请参考以下文章

使用 JointCode.Shuttle 进行跨 AppDomain 通信的一个简单示例

使用 JointCode.Shuttle 访问任意 AppDomain 的服务

AppDomains之间的通信

AppDomain 通信和性能

跨AppDomain通信问题

C# AppDomain 类