AppDomain 间通信和接口
Posted
技术标签:
【中文标题】AppDomain 间通信和接口【英文标题】:inter-AppDomain communication and interfaces 【发布时间】:2013-09-12 18:42:45 【问题描述】:我正在寻找一种将组件(基于第 3 方 dll)隔离在可卸载的单独 AppDomain 中的方法。我的计划是使用基于CreateInstanceAndUnwrap
和MarshalByRefObject
的对象与组件进行通信。
问题是,为了在主程序集中使用从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 通信的一个简单示例