2

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

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

class MyObject: MarshalByRefObject, IMyObject
{
}

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

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

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

4

1 回答 1

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();
于 2013-09-12T18:52:18.093 回答