Mixing MarshalByRefObject and Serializable

后端 未结 2 1837
梦如初夏
梦如初夏 2020-12-31 22:52

Various sources explain that

When an object derives form MarshalByRefObject, an object reference will be passed from one application domain to anoth

2条回答
  •  猫巷女王i
    2020-12-31 23:42

    I just did a quick test with List and it seems to work as I had hoped:

    public class MBR : MarshalByRefObject
    {
        List _list;
        public MBR() { _list = new List { this }; }
        public IList Test() { return _list; }
        public int X { get; set; }
    }
    
    // Later...
    var mbr = AppDomainStarter.Start(@"C:\Program Files", "test", null, true);
    var list = mbr.Test();
    list[0].X = 42;
    list.Clear();
    Debug.WriteLine(string.Format("X={0}, Count={1}", mbr.X, mbr.Test().Count));
    

    The output is X=42, Count=1, and the debugger shows that the List contains a __TransparentProxy. So clearly, the MarshalByRefObject is successfully marshaled by reference inside another object that was marshaled by value.

    I would still like to see documentation or technical details if anyone can find some.

    For anyone who is curious, I wrote this handy-dandy sandbox AppDomainStarter:

    ///  starts an AppDomain.
    public static class AppDomainStarter
    {
        /// Creates a type in a new sandbox-friendly AppDomain.
        /// A trusted type derived MarshalByRefObject to create 
        /// in the new AppDomain. The constructor of this type must catch any 
        /// untrusted exceptions so that no untrusted exception can escape the new 
        /// AppDomain.
        /// Value to use for AppDomainSetup.ApplicationBase.
        /// The AppDomain will be able to use any assemblies in this folder.
        /// A friendly name for the AppDomain. MSDN
        /// does not state whether or not the name must be unique.
        /// Arguments to send to the constructor of T,
        /// or null to call the default constructor. Do not send arguments of 
        /// untrusted types this way.
        /// Whether the new AppDomain should run in 
        /// partial-trust mode.
        /// A remote proxy to an instance of type T. You can call methods 
        /// of T and the calls will be marshalled across the AppDomain boundary.
        public static T Start(string baseFolder, string appDomainName, 
            object[] constructorArgs, bool partialTrust)
            where T : MarshalByRefObject
        {
            // With help from http://msdn.microsoft.com/en-us/magazine/cc163701.aspx
            AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationBase = baseFolder;
    
            AppDomain newDomain;
            if (partialTrust) {
                var permSet = new PermissionSet(PermissionState.None);
                permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
                permSet.AddPermission(new UIPermission(PermissionState.Unrestricted));
                newDomain = AppDomain.CreateDomain(appDomainName, null, setup, permSet);
            } else {
                newDomain = AppDomain.CreateDomain(appDomainName, null, setup);
            }
            return (T)Activator.CreateInstanceFrom(newDomain, 
                typeof(T).Assembly.ManifestModule.FullyQualifiedName, 
                typeof(T).FullName, false,
                0, null, constructorArgs, null, null).Unwrap();
        }
    }
    

提交回复
热议问题