用于将POCO实例暴露给其他AppDomain的通用容器 - 它是如何工作的?

时间:2009-04-30 12:55:32

标签: c# generics appdomain poco marshalbyrefobject

我对来自另一个SO线程的this回答很感兴趣,我希望有人可以帮助我对这个概念有所启发。

假设我有一个主AppDomain和一堆子AppDomain,它们是由主AppDomain创建和初始化的。在伪代码中:

主AppDomain:

class Parent
{
    public void InitChildren(IList<ChildInfo> children)
    {
        foreach (var childInfo in children)
        {
            var ad = CreateNewChildAppDomain();
            var child = (Child)ad.CreateInstanceAndUnwrap(typeof(Child));
            child.Init(this);
        }
    }

    public void Register(BasePoco info)
    {
        // Do something with info.
    }
}

Child AppDomain:

class Child : MarshalByRefObject
{
    public void Init(Parent parent)
    {
        parent.Register(new Container<MyInfo>(new MyInfo()));
    }
}

class MyInfo : BasePoco // <- not a MarshalByRefObject!
{
    public MyInfo() { ... }
}

在Init()期间,子AppDomain实例化POCO对象,该对象根据定义是不可编组的。我们也假设我们不能在这方面修改它。

链接的答案表明将其包装在Container<T>(其本身 可编组)中应该允许将其传递回主AppDomain。我理解这一点,因为它是真正传递的Container<MyInfo>实例的代理。

我不明白主AppDomain如何通过容器代理访问容器中的POCO实例。我在Container<T>中看到了重载的隐式强制转换操作符,我理解它返回包含的POCO实例。但是那个实例本身并没有被代理 - 它仍然存在于AppDomain中!那么,这不应该打破吗?

这里到底发生了什么?

1 个答案:

答案 0 :(得分:1)

只要容器返回另一个AppDomain中的实例(无论是通过Value属性还是隐式转换运算符),该对象就会被编组。如果它是MarshalByRefObject,则会生成一个新代理,以便您可以访问它。否则,该对象将被复制(按值编组,序列化)到当前应用程序域中。

该问题中显示的Container类唯一可以帮助的是,如果要将代理保留给另一个不应该编组的对象。但在这种情况下,您不能访问Value属性或使用代理所在的AppDomain中的隐式转换运算符,因为这会导致容器中的对象被封送。仍然,您可以将容器作为参数使用与生活在与Container对象相同的AppDomain中的对象的方法,因此基本上允许您保持对非可编组对象的引用(不可序列化而不是MarshalByRef或类型在一个无法使用代理等加载到AppDomain的程序集中)并像“句柄”一样传递它。