各种消息来源都解释说
当对象派生自MarshalByRefObject时,对象引用将从一个应用程序域传递到另一个应用程序域,而不是对象本身。当一个对象被标记为可序列化时,该对象将自动序列化,从一个应用程序域传输到另一个应用程序域,然后反序列化以生成第二个应用程序域中的对象的确切副本。然后请注意,当MarshalByRefObject传递一个引用时,可序列化会导致对象被复制。[来源]
我正在设计我的第一个使用AppDomains的应用程序,我想知道当您将对MarshalByRefObjects的引用放在没有实现MarshalByRefObject的可序列化对象中时会发生什么,因为到目前为止我还没有找到关于这个主题的任何文档。
例如,如果我试图返回一个跨越List<MBR>边界的MBR : MarshalByRefObject的AppDomain,会发生什么?我是否得到List<MBR>的副本,其中每个MBR都是原始对象的TransparentProxy?是否有关于混合这两种机制的技术细节的文档?
发布于 2012-01-08 00:56:20
我刚刚用List<MBR>做了一个快速测试,它似乎如我所希望的那样起作用了:
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<MBR>包含一个__TransparentProxy。因此很明显,MarshalByRefObject是通过引用在另一个被值封送的对象中成功地封送的。
我仍然希望看到文档或技术细节,如果有人可以找到一些。
对于任何好奇的人,我写了一个方便的沙箱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();
}
}发布于 2012-01-07 23:44:53
据我理解,只有通过的顶级对象才可能是MBR。在您的场景中,由于List不是MBR,所以当它通过边界时,您将收到序列化的副本。
MSDN文档中的这个部分解释了这种行为:
MarshalByRefObject是通过使用代理交换消息跨应用程序域边界进行通信的对象的基类。不从MarshalByRefObject继承的对象按值隐式封送。当远程应用程序通过值对象引用封送件时,对象的副本将跨应用程序域边界传递。
因此,由于传递的类(列表)不是MBR,它将与其内容一起序列化。
此外,虽然不直接适用于这个问题,但以下行为非常重要:
..。对象的成员在创建它们的应用程序域之外是不可用的。
https://stackoverflow.com/questions/8773814
复制相似问题