public MarshalByValType MethodWithReturn() { Console.WriteLine($"Executing in {Thread.GetDomain().FriendlyName}"); MarshalByValType t = new MarshalByValType(); return(t); }
private static void Marshalling() { // Получаем ссылку на домен, в котором исполняется вызывающий поток AppDomain adCallingThreadDomain = Thread.GetDomain(); // Каждому домену присваивается значимое имя, облегчающее отладку // Получаем имя домена и выводим его string callingDomainName = adCallingThreadDomain.FriendlyName; Console.WriteLine($"Default AppDomain's friendly name = {callingDomainName}"); // Получаем и выводи сборку в домене, содержащем метод Main string exeAssembly = Assembly.GetEntryAssembly().FullName; Console.WriteLine($"Main assembly = {exeAssembly}"); AppDomain ad2 = null; //Пример №1. доступ к объектам другого домена приложений с продвижением по ссылке Console.WriteLine($"{Environment.NewLine}Demo #1"); //Создаем новый домен (с теми же параметрами защиты и конфигурирования) ad2 = AppDomain.CreateDomain("AD #2", null, null); MarshalByRefType mbrt = null; // Загружаем нашу сборку в новый домен, конструируем объект и продвигаем его обратно в наш домен // (в дейсвительности мы получаем ссылку на представителя) mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "DomainSample.MarshalByRefType"); Console.WriteLine($"Type={mbrt.GetType()}"); //CLR не верно определяет тип //Убеждаемся, что получили ссылку на объект представитель Console.WriteLine($"Is proxy={RemotingServices.IsTransparentProxy(mbrt)}"); // Все выглядит так, как будто мы вызываем метод экземпляра // MarshalByRefType, но на самом деле мы вызываем метод типа // представителя. Именно представитель переносит поток в тот домен, // в котором находится объект, и вызывает метод для реального объекта mbrt.DoSomething(); //Выгружаем новый домен AppDomain.Unload(ad2); //mbrt ссылается на правильный объект-представитель; // объект-представитель ссылается на неправильный домен try { // Вызываем метод, определенный в типе представителя // Поскольку домен приложений неправильный, появляется исключения mbrt.DoSomething(); Console.WriteLine("Successful call"); } catch (AppDomainUnloadedException) { Console.WriteLine("Failed call"); } Console.WriteLine($"{Environment.NewLine}Demo #2"); ad2 = AppDomain.CreateDomain("AD #2", null, null); // Получили представителя mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "DomainSample.MarshalByRefType"); // Метод возвращает копию возвращенного объекта // продвижение объекта происходит по значению, а не по ссылке MarshalByValType mbvt = mbrt.MethodWithReturn(); //Убеждаемся что мы не получили ссылку на объект представитель Console.WriteLine($"Is proxy={RemotingServices.IsTransparentProxy(mbvt)}"); Console.WriteLine($"Returned object created {mbvt.ToString()}"); AppDomain.Unload(ad2); // mbrt ссылается на действительный объект // выгрузка домена не имеет никакого эффекта try { // исключение не генерируется Console.WriteLine($"Returned object created {mbvt.ToString()}"); Console.WriteLine("Success call"); } catch (AppDomainUnloadedException) { Console.WriteLine("Failed call"); } Console.WriteLine($"{Environment.NewLine}Demo #3"); ad2 = AppDomain.CreateDomain("AD #2", null, null); mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "DomainSample.MarshalByRefType"); NonMarsalableType nmt = mbrt.MethodArgAndReturn(callingDomainName); }