views:

233

answers:

1

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?

+1  A: 

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".

Lucero
Thanks, Lucero! I thought as much. :)
aoven