using System; using System.Reflection; using System.Threading; using System.Runtime.InteropServices; namespace TestTwoDomainsAndSingeThread { //[StructLayout(LayoutKind.Explicit)] public unsafe struct Variant { //[FieldOffset(0)] public ushort vt; //[FieldOffset(0)] public ushort wReserved1; //[FieldOffset(0)] public ushort wReserved2; //[FieldOffset(0)] public ushort wReserved3; //[FieldOffset(0)] public IntPtr bstrVal; //[FieldOffset(0)] public Int32 data01; //[FieldOffset(0)] public Int32 data02; } public class Worker : MarshalByRefObject { public unsafe IntPtr GetIntPtrForVariant() { Variant v = new Variant(); IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v)); return pNative; } public unsafe object GetDoubleFromAnotherDomain() { double obj = 3.14; AppDomain yad = AppDomain.CreateDomain("Yet another domain"); Worker remoteWorker = (Worker)yad.CreateInstanceAndUnwrap( typeof(Worker).Assembly.FullName, typeof(Worker).FullName); IntPtr pNative = remoteWorker.GetIntPtrForVariant(); Marshal.GetNativeVariantForObject(obj, pNative); object o = Marshal.GetObjectForNativeVariant(pNative); return o; } } public class Test { static unsafe void Main(string[] args) { double obj = 3.14; AppDomain ad = AppDomain.CreateDomain("New domain"); Worker remoteWorker = (Worker)ad.CreateInstanceAndUnwrap( typeof(Worker).Assembly.FullName, typeof(Worker).FullName); IntPtr pNative = remoteWorker.GetIntPtrForVariant(); Marshal.GetNativeVariantForObject(obj, pNative); Variant result = (Variant)Marshal.PtrToStructure(pNative, typeof(Variant)); Console.WriteLine("VarEnum.VT_R8 name from default domain: " + VarEnum.VT_R8); Console.WriteLine("Result of (VarEnum)result.vt from another domain: " + (VarEnum)result.vt); if (VarEnum.VT_R8 != (VarEnum)result.vt) { Console.WriteLine("Testcase failed"); } else { Console.WriteLine("Testcase passed"); } AppDomain ndfD = AppDomain.CreateDomain("New domain for double"); Worker remoteWorker2 = (Worker)ndfD.CreateInstanceAndUnwrap( typeof(Worker).Assembly.FullName, typeof(Worker).FullName); object o = remoteWorker2.GetDoubleFromAnotherDomain(); Console.WriteLine("3.14 value from default domain: " + obj.ToString()); Console.WriteLine("3.14 value from remote domain: " + o); if (obj.ToString() != o.ToString()) { Console.WriteLine("Testcase failed"); } else { Console.WriteLine("Testcase passed"); } Console.WriteLine("Obj value cast: " + *((ulong*)&obj)); Console.WriteLine("Unwound variant value cast: " + *((ulong*)&result.bstrVal)); Console.ReadLine(); } } }