用于向其他 AppDomain 公开 POCO 实例的通用容器 - 它是如何工作的?
我对另一个线程的这个答案很感兴趣,我希望有人可以帮助我阐明这个概念。
假设我有一个主 AppDomain 和一堆子 AppDomain,它们是由主 AppDomain 创建和初始化的。 在伪代码中:
Primary 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
(其本身可编组)中应允许将其传递回主 AppDomain。 我理解这一点,因为它是真正传递的 Container
实例的代理。
我不明白的是主 AppDomain 如何通过容器代理访问容器中的 POCO 实例。 我在 Container
中看到重载的隐式转换运算符,并且我知道它返回包含的 POCO 实例。 但该实例本身并未被代理 - 它仍然在子 AppDomain 中! 那么,这不应该打破吗?
这里究竟发生了什么?
I'm intrigued by this answer from another SO thread, and I was hoping someone can help me shine some light on the concept.
Say I have a primary AppDomain and a bunch of child AppDomains, that are created and initialized by the primary AppDomain. In pseudo code:
Primary 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() { ... }
}
During Init(), a child AppDomain instantiates a POCO object, which is non-marshalable by definition. Let's also assume we cannot modify it in that regard.
The linked answer suggests that wrapping it in a Container<T>
(which itself is marshalable) should allow it to be passed back to primary AppDomain. I understand this because it's the proxy to Container<MyInfo>
instance that really gets passed across.
What I don't understand is how the primary AppDomain can possibly access the POCO instance in the container through the proxy of the container. I see the overloaded implicit cast operator in Container<T>
and I understand it returns the contained POCO instance. But that instance isn't being proxied itself - it's still in the child AppDomain! So, shouldn't this break?
What's really going on here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一旦容器返回位于其他 AppDomain 中的实例(无论是通过 Value 属性还是隐式转换运算符发生),该对象就会被编组。 如果它是 MarshalByRefObject,则会生成一个新代理,以便您可以访问它。 否则,对象将被复制(按值编组、序列化)到当前应用程序域中。
该问题中显示的 Container 类唯一可以提供帮助的是,如果您想保留另一个不应编组的对象的代理。 但在这种情况下,您不得从代理所在的 AppDomain 访问 Value 属性或使用隐式转换运算符,因为这会导致容器中的对象被封送。 尽管如此,您仍然可以使用容器作为与 Container 对象位于同一 AppDomain 中的对象的方法的参数,因此基本上允许您保留对不可编组对象(不可序列化且不可 MarshalByRef 或某种类型)的引用在无法使用代理等加载到 AppDomain 的程序集中)并将其像“句柄”一样传递。
As soon as the container returns the instance living in the other AppDomain (whether this happens via Value property or implicit conversion operator), the object will be marshalled. If it is a MarshalByRefObject, a new proxy will be generated so you can access it. Otherwise, the object will be copied (marshalled by value, serialized) into the current application domain.
The only thing that the Container class shown in that question can help with is if you want to keep a proxy to another object which should not be marshalled. But in this case, you must not access the Value property or use the implicit conversion operator from the AppDomain where the proxy lives, because this would cause the object in the container to be marshaled. Still, you could use the container as argument into a method on an object living in the same AppDomain as the Container object, therefore basically allowing you to keep a reference to a non-marshallable object (not serializable and not MarshalByRef, or of a type in an assembly which cannot be loaded to the AppDomain with the proxy etc.) and to pass it around like a "handle".