混合MarshalByRefObject的和序列化序列化、MarshalByRefObject

2023-09-03 02:05:03 作者:藏起来的悲凉

各种消息来源解释说,

当一个对象派生形式MarshalByRefObject的,对象引用   将被从一个应用程序域传递到另一个,而不是   对象本身。当一个对象被标记为[Serializable接口]时,   对象将被自动序列,从一个运   应用领域到另一个,然后反序列化,以产生   的对象中的第二应用域精确副本。请注意,然后   虽然MarshalByRefObject的传递一个参考,[Serializable接口]   导致要复制的对象。 【来源】

When an object derives form MarshalByRefObject, an object reference will be passed from one application domain to another rather than the object itself. When an object is marked with [Serializable], the object will be automatically serialized, transported from one application domain to another and then deserialized to produce an exact copy of the object in the second application domain. Note then that while MarshalByRefObject passes a reference, [Serializable] causes the object to be copied. [source]

我设计我使用的AppDomain第一个应用程序,我想知道当你把引用 MarshalByRefObjects 里面的序列化对象没有实现MarshalByRefObject的会发生什么,因为这样到目前为止,我无法找到任何关于这个问题的文件。

I'm designing my first app that uses AppDomains and I'm wondering what happens when you place references to MarshalByRefObjects inside serializable objects that do not implement MarshalByRefObject, because so far I can't find any documentation on the subject.

例如,如果我试图返回名单,其中发生AppDomain的边界?难道我得到的列表℃的副本; MBR> ,其中每个 MBR TransparentProxy 原来的对象?而有关于混合这两种机制的技术细节的任何文档?

For example, what happens if I try to return a List<MBR> where MBR : MarshalByRefObject across an AppDomain boundary? Do I get a copy of the List<MBR> where each MBR is a TransparentProxy to the original object? And is there any documentation about the technical details of mixing the two mechanisms?

推荐答案

我只是做了一个快速测试与名单,其中,MBR&GT; ,似乎工作,我曾希望

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

public class MBR : MarshalByRefObject
{
    List<MBR> _list;
    public MBR() { _list = new List<MBR> { this }; }
    public IList<MBR> Test() { return _list; }
    public int X { get; set; }
}

// Later...
var mbr = AppDomainStarter.Start<MBR>(@"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));

输出为 X = 42,计数= 1 ,调试器显示了名单,其中,MBR&GT; 包含 __ TransparentProxy 。所以很明显,在 MarshalByRefObject的被成功地被编组通过值另一个对象中引用封。

The output is X=42, Count=1, and the debugger shows that the List<MBR> 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.

对于任何人谁是好奇,我写了这个方便,花花公子沙箱AppDomainStarter:

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

/// <summary><see cref="AppDomainStarter.Start"/> starts an AppDomain.</summary>
public static class AppDomainStarter
{
    /// <summary>Creates a type in a new sandbox-friendly AppDomain.</summary>
    /// <typeparam name="T">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.</typeparam>
    /// <param name="baseFolder">Value to use for AppDomainSetup.ApplicationBase.
    /// The AppDomain will be able to use any assemblies in this folder.</param>
    /// <param name="appDomainName">A friendly name for the AppDomain. MSDN
    /// does not state whether or not the name must be unique.</param>
    /// <param name="constructorArgs">Arguments to send to the constructor of T,
    /// or null to call the default constructor. Do not send arguments of 
    /// untrusted types this way.</param>
    /// <param name="partialTrust">Whether the new AppDomain should run in 
    /// partial-trust mode.</param>
    /// <returns>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.</returns>
    public static T Start<T>(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();
    }
}