1

我对另一个 SO 线程的这个答案很感兴趣,我希望有人可以帮助我阐明这个概念。

假设我有一个主 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.
    }
}

子应用域:

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 中!那么,这不应该中断吗?

这里到底发生了什么?

4

1 回答 1

1

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

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

于 2009-04-30T13:31:03.823 回答