本文介绍了混合 MarshalByRefObject 和 Serializable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

各种消息来源解释

当一个对象从 MarshalByRefObject 派生时,一个对象引用将从一个应用程序域传递到另一个应用程序域而不是对象本身.当一个对象被标记为 [Serializable] 时,对象将被自动序列化,从一个传输应用程序域到另一个,然后反序列化以产生一个第二个应用程序域中对象的精确副本.然后注意当 MarshalByRefObject 传递一个引用时,[Serializable]导致对象被复制.[来源]

我正在设计我的第一个使用 AppDomains 的应用程序,我想知道当您在未实现 MarshalByRefObject 的可序列化对象中放置对 MarshalByRefObjects 的引用时会发生什么,因为到目前为止我找不到有关该主题的任何文档.

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 边界返回 List 其中 MBR : MarshalByRefObject 会发生什么?我是否获得了 List 的副本,其中每个 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?

推荐答案

我刚刚用 List 做了一个快速测试,它似乎如我所愿:

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, Count=1,调试器显示 List 包含一个 __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();
    }
}

这篇关于混合 MarshalByRefObject 和 Serializable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-09 10:17