Accessing objects across AppDomain boundaries
Change the code in the book (3) to "Marshalbyreftype" to "typeof (Marshalbyreftype)." FullName ", you can get the output from the book:
Will: Marshalbyreftype MBRT = (marshalbyreftype) ad2. Createinstanceandunwrap (exeassembly, "Marshalbyreftype");
Modified to: Marshalbyreftype MBRT = (marshalbyreftype) ad2. Createinstanceandunwrap (exeassembly, typeof (Marshalbyreftype). FullName);
The modified code is:
Using System;
Using System.Collections.Generic;
Using System.Linq;
Using System.Text;
Using System.Threading;
Using System.Reflection;
Using System.Runtime.Remoting;
Namespace Clrappdomain
{
public class Marshal
{
private static void marshaling ()
{
Gets a reference to the AppDomain (the calling thread executes in the AppDomain)
AppDomain Adcallingthreaddomain = Thread.getdomain ();
Each AppDomain has a friendly string name, gets the name and displays
string callingdomainname = Adcallingthreaddomain.friendlyname;
Console.WriteLine ("Defalut AppDomain ' s friendly name={0}", Callingdomainname);
Get & Show Assemblies in our AppDomain that contain the "Main" method
String exeassembly = assembly.getentryassembly (). FullName;
Console.WriteLine ("Main assembly={0}", exeassembly);
Define a local variable reference an AppDomain
Demo 1, using marshal-by-reference for cross-AppDomain communication * * *
Console.WriteLine ("{0}*** Demo #1", Environment.NewLine);
Create a new AppDomain, security and configuration matching with the current AppDomain
AppDomain ad2 = Appdomain.createdomain ("AD #2", NULL, NULL);
Load our assembly into the AppDomain, construct an object, marshal it to our AppDomain
is actually getting a proxy reference
Marshalbyreftype MBRT = (marshalbyreftype) ad2. Createinstanceandunwrap (exeassembly, typeof (Marshalbyreftype). FullName);
Console.WriteLine ("Type={0}", MBRT. GetType ());//Here The CLR is lying on the type, getting type=appdomainlib.mashalbyreftype, not really.
The proof is a reference to a proxy
Console.WriteLine ("Is proxy={0}", Remotingservices.istransparentproxy (MBRT));
It looks like a method of Mashalbyreftype up in the
We called a method on the proxy type, and the agent switched the thread to the owning object
The AppDomain
MBRT. Somemehtod ();
Uninstalling the new AppDomain
AppDomain.Unload (AD2);
MBRT references an invalid proxy object, and the proxy object references an invalid AppDomain
Try
{
MBRT. Somemehtod ();
}
catch (AppDomainUnloadedException)
{
Console.WriteLine ("Fall call");
}
Demo 2, using Marshal-by-value for cross-AppDomain communication * * *
Console.WriteLine ("{0}*** Demo #2", Environment.NewLine);
//New AppDomain, security and configuration matching with current appdomain
Ad2 = Appdomain.createdomain ("AD #2", NULL, NULL);
// Loading our assembly into the AppDomain, constructing an object, marshaling it to our AppDomain
//actually getting a proxy reference
MBRT = (marshalbyreftype) ad2. Createinstanceandunwrap (exeassembly, typeof (Marshalbyreftype). FullName); The method of the
//object returns a copy of the returned object
//The returned object is marshaled by value (not by reference)
Marshalbyvaltype MBV = mbrt. Methodwidthreturn ();
//Prove that we are not getting a reference to a proxy object
Console.WriteLine ("Is porxy={0}", Remotingservices.istransparentproxy (MBV));
// It looks like the method was called on Marshalbyvaltype, and the fact is that
Console.WriteLine ("Return Object create:{0}", MBV. ToString ());
//Uninstall AppDomain
AppDomain.Unload (ad2);
//MBV Reference valid object, uninstall AppDomain does not affect
try
{
//We are calling a method on an object, All will not throw an exception
Console.WriteLine ("Return Object create:{0}", MBV. ToString ());
}
catch (appdomainunloadedexception)
{
Console.WriteLine ("Fail call");
}
//*** Demo 3 uses non-marshaled types for AppDomain communication
Console.WriteLine ("{0}*** Demo #3", Environment.NewLine);
// Create a new AppDomain, security and configuration matching with the current appdomain
Ad2 = Appdomain.createdomain ("AD #2", NULL, NULL);
//Load our assemblies into the AppDomain , construct an object, marshal it to our AppDomain
//actually get a proxy reference
MBRT = (marshalbyreftype) ad2. Createinstanceandunwrap (exeassembly, typeof (Marshalbyreftype). FullName); The method of the
//object returns an object that is not marshaled, throws an exception
Nonmarshalabletype NMT = mbrt. Methodargandreturn (Callingdomainname);
//The code here never executes ...
}
public static void Main ()
{
Marshaling ();
}
}
//Instances of this class can be marshaled by reference across the AppDomain's boundaries
public sealed class Marshalbyreftype:marshalbyrefobject
{
Public Marshal Byreftype ()
{
Console.WriteLine (' {0}. ctor running in {1} ', this. GetType (). Name, Thread.getdomain (). FriendlyName);
}
public void Somemehtod ()
{
Console.WriteLine (' Executing is ' + thread.getdomain (). FriendlyName);
}
Public Marshalbyvaltype Methodwidthreturn ()
{
Console.WriteLine (' Executing is ' + thread.getdomain (). FriendlyName);
Marshalbyvaltype t = new Marshalbyvaltype ();
return t;
}
Public Nonmarshalabletype Methodargandreturn (string callingdomainname)
{
// Note that Callingdomainname is a
Console.WriteLine ("Calling from {0} to {1}", Callingdomainname, Thread.getdomain () that can be serialized. FriendlyName);
Nonmarshalabletype t = new Nonmarshalabletype ();
return t;
}
}
Instances of this class can "marshal by value" across the AppDomain's boundary
[Serializable]
public sealed class Marshalbyvaltype:object
{
private datetime m_createtime = datetime.now;//Note datetime is serializable
Public Marshalbyvaltype ()
{
Console.WriteLine ("{0} ctor running in {1},create to {2}", this. GetType (). ToString (),
Thread.getdomain (). FriendlyName, M_createtime);
}
public override string ToString ()
{
return m_createtime.tolongdatestring ();
}
}
Instances of this class cannot be marshaled across the AppDomain
[Serializable]
public sealed class Nonmarshalabletype:object
{
Public Nonmarshalabletype ()
{
Console.WriteLine ("Executing in {0}", Thread.getdomain (). FriendlyName);
}
}
}
CLR via C # 22nd CLR host and AppDomain access objects across AppDomain boundaries