MarshalByRefObject передаётся по ссылке или делает копию?

Рейтинг: 13Ответов: 1Опубликовано: 02.10.2014

Есть 2 AppDomain с LoaderOptimization = LoaderOptimization.MultiDomainHost.
Есть общая сборка, скажем Common.dll, которая загружена в AppDomain1 и в AppDomain2.
В сборке Common.dll есть класс:

class MethodArgs:MarshalByRefObject  
{
    public string MethodName { get; private set; }
    ...
}

При передаче экземпляра этого класса из AppDomain1 в AppDomain2 передача идёт по ссылке или всё же копируется, а потом делается ссылка?

Ответы

▲ 10

Несмотря на название класса MarshalByRefObject, передача происходит не совсем по ссылке. Упрощенная схема выглядит примерно так:

  1. На вызывающей стороне создается два прокси - System.Runtime.Remoting.Proxies.__TransparentProxy, который по всем признакам является объектом оригинального типа - MethodArgs, и RealProxy, который умеет перебрасывать вызов в другой домен.
  2. Рантайм перехватывает все обращения к методам и свойствам прокси, и проверяет, находится ли их реальный объект для этого __TransparentProxy в другом домене. Если объект в том же домене - то происходит простой вызов метода.
  3. Иначе - рантайм собирает все параметры, оборачивает их в IMessage, и отдает его в метод RealProxy.Invoke(...).
  4. RealProxy (точнее, его реализация для кросс-доменных вызовов) перебрасывает вызов в другой домен, десериализует параметры и вызывает метод у реального объекта.

__TransparentProxy - системный класс, и его поведение нельзя поменять.

Поведение RealProxy, напротив, можно полностью кастомизировать, что позволяет использовать его, например, трассировки/подмены результатов вызовов - создания моков. Или для балансировки нагрузки - перенаправления вызовов от одного __TransparentProxy к нескольким реальным объектам.

Аттрибут LoaderOptimization.MultiDomainHost не оказывает никакого влияния на поведение MarshalByRefObject.

Более подробно о механизме proxy в ремоутинге: