Общий контейнер для предоставления экземпляров POCO другим доменам приложений — как это работает?
-
03-07-2019 - |
Вопрос
я заинтригован этот ответ из другой темы SO, и я надеялся, что кто-нибудь поможет мне пролить свет на эту концепцию.
Допустим, у меня есть основной домен приложения и несколько дочерних доменов приложений, которые создаются и инициализируются основным доменом приложения.В псевдокоде:
Основной домен приложения:
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>
(что само по себе является marshalable) должен разрешить его передачу обратно в основной домен приложения.Я понимаю это, потому что это прокси для Container<MyInfo>
экземпляр, который действительно передается.
Чего я не понимаю, так это того, как основной домен приложения может получить доступ к экземпляру POCO в контейнере через прокси контейнера.Я вижу перегруженный оператор неявного приведения в Container<T>
и я понимаю, что он возвращает содержащийся экземпляр POCO.Но сам этот экземпляр не проксируется — он все еще находится в дочернем домене приложений!Так разве это не должно сломаться?
Что здесь происходит на самом деле?
Решение
Как только контейнер вернет экземпляр, находящийся в другом AppDomain (происходит ли это через свойство Value или оператор неявного преобразования), объект будет маршалирован.Если это MarshalByRefObject, будет создан новый прокси-сервер, чтобы вы могли получить к нему доступ.В противном случае объект будет скопирован (упорядочен по значению, сериализован) в текущий домен приложения.
Единственное, в чем может помочь класс Container, показанный в этом вопросе, - это если вы хотите сохранить прокси для другого объекта, который не следует маршалировать.Но в этом случае вы не должны обращаться к свойству Value или использовать оператор неявного преобразования из AppDomain, где находится прокси, поскольку это приведет к маршалированию объекта в контейнере.Тем не менее, вы можете использовать контейнер в качестве аргумента в методе объекта, находящегося в том же AppDomain, что и объект Container, что в основном позволяет вам сохранять ссылку на немаршализуемый объект (не сериализуемый и не MarshalByRef или типа в сборке, которую нельзя загрузить в AppDomain с помощью прокси и т. д.) и передать ее как «дескриптор».