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

1,00
р.
Есть 2 AppDomain с LoaderOptimization = LoaderOptimization.MultiDomainHost. Есть общая сборка, скажем Common.dll, которая загружена в AppDomain1 и в AppDomain2. В сборке Common.dll есть класс:
class MethodArgs:MarshalByRefObject { public string MethodName { get private set } ... }
При передаче экземпляра этого класса из AppDomain1 в AppDomain2 передача идёт по ссылке или всё же копируется, а потом делается ссылка?


Ответ
Несмотря на название класса MarshalByRefObject, передача происходит не совсем по ссылке. Упрощенная схема выглядит примерно так:
На вызывающей стороне создается два прокси - System.Runtime.Remoting.Proxies.__TransparentProxy, который по всем признакам является объектом оригинального типа - MethodArgs, и RealProxy, который умеет перебрасывать вызов в другой домен. Рантайм перехватывает все обращения к методам и свойствам прокси, и проверяет, находится ли их реальный объект для этого __TransparentProxy в другом домене. Если объект в том же домене - то происходит простой вызов метода. Иначе - рантайм собирает все параметры, оборачивает их в IMessage, и отдает его в метод RealProxy.Invoke(...). RealProxy (точнее, его реализация для кросс-доменных вызовов) перебрасывает вызов в другой домен, десериализует параметры и вызывает метод у реального объекта.
__TransparentProxy - системный класс, и его поведение нельзя поменять.
Поведение RealProxy, напротив, можно полностью кастомизировать, что позволяет использовать его, например, трассировки/подмены результатов вызовов - создания моков. Или для балансировки нагрузки - перенаправления вызовов от одного __TransparentProxy к нескольким реальным объектам.
Аттрибут LoaderOptimization.MultiDomainHost не оказывает никакого влияния на поведение MarshalByRefObject.
Более подробно о механизме proxy в ремоутинге:
Microsoft .NET Remoting: A Technical Overview Transparent Proxy