private static void Marshalling() { //获取当前线程在那个AppDomain,效果相同 var xad = Thread.GetDomain(); var xad2 = System.AppDomain.CurrentDomain; // Get a reference to the AppDomain that that calling thread is executing in AppDomain adCallingThreadDomain = Thread.GetDomain(); // Every AppDomain is assigned a friendly string name (helpful for debugging) // Get this AppDomain's friendly string name and display it String callingDomainName = adCallingThreadDomain.FriendlyName; Console.WriteLine("Default AppDomain's friendly name={0}", callingDomainName); // Get & display the assembly in our AppDomain that contains the 'Main' method String exeAssembly = Assembly.GetEntryAssembly().FullName; Console.WriteLine("Main assembly={0}", exeAssembly); // Define a local variable that can refer to an AppDomain AppDomain ad2 = null; // *** DEMO 1: Cross-AppDomain Communication using Marshal-by-Reference #region demo1 Console.WriteLine("{0}Demo #1", Environment.NewLine); // Create new AppDomain (security & configuration match current AppDomain) ad2 = AppDomain.CreateDomain("AD #2", null, null); MarshalByRefType mbrt = null; // Load our assembly into the new AppDomain, construct an object, marshal // it back to our AD (we really get a reference to a proxy) // 这一步导致线程切换到新的 AppDomain mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType"); // 执行完后,线程切换回来 // The CLR lies about the type // 1. 在内存中,mbrt的真正类型是一个「代理类型」,它有几个私有字段标明了「源AppDomain和 源对象」 // 2. mbrt的getType,做了特殊处理,返回「源对象」的类型 Console.WriteLine("Type={0}", mbrt.GetType()); // Prove that we got a reference to a proxy object // IsTransparentProxy,通过这个方法,证明mbrt确实是「代理类型」 Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); // This looks like we're calling a method on MarshalByRefType but, we're not. // We're calling a method on the proxy type. The proxy transitions the thread「切换」 // to the AppDomain owning the object and calls this method on the real object. mbrt.SomeMethod(); // Unload the new AppDomain AppDomain.Unload(ad2); // mbrt refers to a valid proxy object; the proxy object refers to an invalid AppDomain try { // We're calling a method on the proxy type. The AD is invalid, exception is thrown mbrt.SomeMethod(); Console.WriteLine("Successful call."); } catch (AppDomainUnloadedException) { Console.WriteLine("Failed call."); } #endregion // *** DEMO 2: Cross-AppDomain Communication using Marshal-by-Value #region demo2 Console.WriteLine("{0}Demo #2", Environment.NewLine); // Create new AppDomain (security & configuration match current AppDomain) ad2 = AppDomain.CreateDomain("AD #2", null, null); // Load our assembly into the new AppDomain, construct an object, marshal // it back to our AD (we really get a reference to a proxy) mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType"); // The object's method returns a COPY of the returned object; // the object is marshaled by value (not be reference). MarshalByValType mbvt = mbrt.MethodWithReturn(); // Prove that we did NOT get a reference to a proxy object Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbvt)); // This looks like we're calling a method on MarshalByValType and we are. Console.WriteLine("Returned object created " + mbvt.ToString()); // Unload the new AppDomain AppDomain.Unload(ad2); // mbvt refers to valid object; unloading the AppDomain has no impact. try { // We're calling a method on an object; no exception is thrown Console.WriteLine("Returned object created " + mbvt.ToString()); Console.WriteLine("Successful call."); } catch (AppDomainUnloadedException) { Console.WriteLine("Failed call."); } #endregion // DEMO 3: Cross-AppDomain Communication using non-marshalable type #region demo3 Console.WriteLine("{0}Demo #3", Environment.NewLine); // Create new AppDomain (security & configuration match current AppDomain) ad2 = AppDomain.CreateDomain("AD #2", null, null); // Load our assembly into the new AppDomain, construct an object, marshal // it back to our AD (we really get a reference to a proxy) mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType"); // The object's method returns an non-marshalable object; exception try { NonMarshalableType nmt = mbrt.MethodArgAndReturn(callingDomainName); } catch (Exception ex) { Console.WriteLine(ex.Message); } // We won't get here... #endregion }
public static void RunAndExplore() { // Get a reference to the AppDomain that the calling thread is executing in AppDomain adCallingThreadDomain = Thread.GetDomain(); // Every AppDomain is assigned a friendly string name (helpful for debugging) // Get this AppDomain's friendly string name and display it String callingDomainName = adCallingThreadDomain.FriendlyName; Console.WriteLine("Default AppDomain's friendly name={0}", callingDomainName); // Get and display the assembly in our AppDomain that contains the 'Main' method String exeAssembly = Assembly.GetEntryAssembly().FullName; Console.WriteLine("Main assembly={0}", exeAssembly); // Define a local variable that can refer to an AppDomain AppDomain ad2 = null; #region *** DEMO 1: CrossAppDomain Communication Using MarshalbyReference *** Console.WriteLine("{0}Demo #1", Environment.NewLine); // Create new AppDomain (security and configuration match current AppDomain) ad2 = AppDomain.CreateDomain("AD #2", null, null); MarshalByRefType mbrt = null; // Load our assembly into the new AppDomain, construct an object, marshal // it back to our AD (we really get a reference to a proxy) mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, typeof(MarshalByRefType).FullName); Console.WriteLine("Type={0}", mbrt.GetType()); // The CLR lies about the type // Prove that we got a reference to a proxy object Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); Console.WriteLine("Try call SomeMethod()"); // This looks like we're calling a method on MarshalByRefType but we're not. // We're calling a method on the proxy type. The proxy transitions the thread // to the AppDomain owning the object and calls this method on the real object. mbrt.SomeMethod(); Console.WriteLine("Successful call."); Console.WriteLine("Unload the {0}", ad2.FriendlyName); // Unload the new AppDomain AppDomain.Unload(ad2); // mbrt refers to a valid proxy object; the proxy object refers to an invalid AppDomain try { Console.WriteLine("Try call SomeMethod()"); // We're calling a method on the proxy type. The AD is invalid, exception is thrown mbrt.SomeMethod(); Console.WriteLine("Successful call."); } catch (AppDomainUnloadedException e) { Console.WriteLine("Failed call - {0}", e.GetType()); } #endregion #region *** DEMO 2: CrossAppDomain Communication Using MarshalbyValue *** Console.WriteLine("{0}Demo #2", Environment.NewLine); // Create new AppDomain (security and configuration match current AppDomain) ad2 = AppDomain.CreateDomain("AD #2", null, null); // Load our assembly into the new AppDomain, construct an object, marshal // it back to our AD (we really get a reference to a proxy) mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, typeof(MarshalByRefType).FullName); // The object's method returns a COPY of the returned object; // the object is marshaled by value (not by reference). MarshalByValType mbvt = mbrt.MethodWithReturn(); // Prove that we did NOT get a reference to a proxy object Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbvt)); // This looks like we're calling a method on MarshalByValType and we are. Console.WriteLine("Returned object created, try call ToString() call \r\n" + mbvt.ToString()); Console.WriteLine("Successful call."); Console.WriteLine("Unload the {0}", ad2.FriendlyName); // Unload the new AppDomain AppDomain.Unload(ad2); // mbvt refers to valid object; unloading the AppDomain has no impact. try { // We're calling a method on an object; no exception is thrown Console.WriteLine("Returned object created try call ToString() call \r\n" + mbvt.ToString()); Console.WriteLine("Successful call."); } catch (AppDomainUnloadedException e) { Console.WriteLine("Failed call - {0}", e.GetType()); } #endregion #region *** DEMO 3: CrossAppDomain Communication Using nonmarshalable type *** Console.WriteLine("{0}Demo #3", Environment.NewLine); // Create new AppDomain (security and configuration match current AppDomain) ad2 = AppDomain.CreateDomain("AD #2", null, null); // Load our assembly into the new AppDomain, construct an object, marshal // it back to our AD (we really get a reference to a proxy) mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, typeof(MarshalByRefType).FullName); try { // The object's method returns a nonmarshalable object; NonMarshalableType nmt = mbrt.MethodArgAndReturn(callingDomainName); // exception Console.WriteLine("Successful call."); // We won't get here... } catch (SerializationException e) { Console.WriteLine("Failed call - {0}", e.GetType()); } Console.ReadKey(); #endregion }
private static void Marshalling() { AppDomain adCallingThreadDomain = Thread.GetDomain(); string callingDomainName = adCallingThreadDomain.FriendlyName; Console.WriteLine("Default AppDomain's friendly name={0}", callingDomainName); string exeAssembly = Assembly.GetEntryAssembly().FullName; Console.WriteLine("Main assembly={0}", exeAssembly); AppDomain ad2 = null; // *** DEMO 1:使用Marshal-by-Reference进行跨APPDomain通信 *** Console.WriteLine("{0}Demo #1", Environment.NewLine); // 新建一个AppDomain(从当前AppDomain继承安全性和配置) ad2 = AppDomain.CreateDomain("AD #2", null, null); MarshalByRefType mbrt = null; // 将我们的程序集加载到新AppDomain中,构造一个对象,把它 // 封送回我们的AppDomain(实际得到对一个代理的引用) mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType"); // CLR 在类型上撒谎了 Console.WriteLine("Type={0}", mbrt.GetType()); // 证明得到的是对一个代理对象的引用 Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); // 看起来像是在MarshalByRefType上调用一个方法,实则不然 // 我们是在代理类型上调用一个方法,代理使线程切换到拥有对象的 // 那个AppDomain,并在真实的对象上调用这个方法 mbrt.SomeMethod(); // 卸载新的AppDomain AppDomain.Unload(ad2); // mbrt引用一个有效的代理对象;代理对象引用一个无效的AppDomain try { // 在代理类型上调用一个方法,AppDomain无效,造成抛出异常 mbrt.SomeMethod(); Console.WriteLine("Successful call."); } catch (AppDomainUnloadedException) { Console.WriteLine("Failed call."); } // *** DEMO 2:使用Marshal-by-Value进行跨AppDomain通信 *** Console.WriteLine("{0}Demo #2", Environment.NewLine); // 新建一个AppDomain(从当前AppDomain继承安全性和配置) ad2 = AppDomain.CreateDomain("AD #2", null, null); // 将我们的程序集加载到新AppDomain中,构造一个对象,把它 // 封送回我们的AppDomain(实际得到对一个代理的引用) mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType"); // 对象的方法返回所返回对象的副本; // 对象按值(而非按引用)封送 MarshalByValType mbvt = mbrt.MethodWithReturn(); // 证明得到的不是对一个代理对象的引用 Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbvt)); // 看起来是在MarshalByValType上调用一个方法,实际也是如此 Console.WriteLine("Returned object created " + mbvt.ToString()); // 卸载新的AppDomain AppDomain.Unload(ad2); // mbvt引用有效的对象:卸载AppDomain没有影响 try { // 我们是在对象上调用一个方法:不会抛出异常 Console.WriteLine("Returned object created " + mbvt.ToString()); Console.WriteLine("Successful call."); } catch (AppDomainUnloadedException) { Console.WriteLine("Failed call."); } // DEMO 3: 使用不可封送的类型进行跨AppDomain通信 *** Console.WriteLine("{0}Demo #3", Environment.NewLine); // 新建一个AppDomain(从当前AppDomain继承安全性和配置) ad2 = AppDomain.CreateDomain("AD #2", null, null); // 将我们的程序集加载到新AppDomain中,构造一个对象,把它 // 封送回我们的AppDomain(实际得到对一个代理的引用) mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType"); // 对象的方法返回一个不可封送的对象:抛出异常 NonMarshalableType nmt = mbrt.MethodArgAndReturn(callingDomainName); // 这里永远执行不到... }
public static void MainAppdomainAndHost() { Console.WriteLine(Guid.NewGuid()); //Clr via 528页 //获取对Appdomain的一个引用 AppDomain adCallThreadDomain = Thread.GetDomain(); String callingDomainName = adCallThreadDomain.FriendlyName; Console.WriteLine("Default AppDomain's friendly name={0}", callingDomainName); String exeAssembly = Assembly.GetEntryAssembly().FullName; Console.WriteLine("Main assembly={0}", callingDomainName); AppDomain ad2 = null; Console.WriteLine("{0} Demo #1", Environment.NewLine); ad2 = AppDomain.CreateDomain("Ad #2", null, null); MarshalByRefType mbrt = null; mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType"); //CLR在类型上撒谎 Console.WriteLine("Type={0}", mbrt.GetType()); //证明得到的是一个代理对象的引用 Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); mbrt.SomeMethod(); AppDomain.Unload(ad2); try { mbrt.SomeMethod(); Console.WriteLine("Successful call."); } catch (Exception) { Console.WriteLine("Failed call."); } Console.WriteLine("{0} Demo #2", Environment.NewLine); ad2 = AppDomain.CreateDomain("Ad #2", null, null); mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType"); MarshalByValType mbvt = mbrt.MethodWithReturn(); Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbvt)); Console.WriteLine("Returned object created {0}", mbvt); AppDomain.Unload(ad2); try { Console.WriteLine("Returned object created {0}", mbvt); Console.WriteLine("Successful call."); } catch (Exception) { Console.WriteLine("Failed call."); } Console.WriteLine("{0} Demo #3", Environment.NewLine); ad2 = AppDomain.CreateDomain("Ad #2", null, null); mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "MarshalByRefType"); NonMarshalableType nmt = mbrt.MethodArgAndReturn(callingDomainName); Console.WriteLine("Continue......."); Console.Read(); }