我对来自另一个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中!那么,这不应该打破吗?
这里到底发生了什么?
答案 0 :(得分:1)
只要容器返回另一个AppDomain中的实例(无论是通过Value属性还是隐式转换运算符),该对象就会被编组。如果它是MarshalByRefObject,则会生成一个新代理,以便您可以访问它。否则,该对象将被复制(按值编组,序列化)到当前应用程序域中。
该问题中显示的Container类唯一可以帮助的是,如果要将代理保留给另一个不应该编组的对象。但在这种情况下,您不能访问Value属性或使用代理所在的AppDomain中的隐式转换运算符,因为这会导致容器中的对象被封送。仍然,您可以将容器作为参数使用与生活在与Container对象相同的AppDomain中的对象的方法,因此基本上允许您保持对非可编组对象的引用(不可序列化而不是MarshalByRef或类型在一个无法使用代理等加载到AppDomain的程序集中)并像“句柄”一样传递它。