que acabo de hacer una prueba rápida con List<MBR>
y parece que funciona como esperaba:
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));
La salida es X=42, Count=1
y el depurador muestra que el List<MBR>
contiene una __TransparentProxy
. Entonces, claramente, el MarshalByRefObject
se calcula con éxito por referencia dentro de otro objeto que se calculó por valor.
Todavía me gustaría ver documentación o detalles técnicos si alguien puede encontrar alguno.
Para cualquier persona que tenga curiosidad, he escrito este práctico-excelente AppDomainStarter caja de arena:
/// <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();
}
}
Así que si MBR no es Serializable, habrá una excepción de algún tipo cuando el .NET Framework intenta serializarlo ? ¿Qué hay de devolver matrices MBR []? System.Array es serializable y no derivado de MarshalByRefObject. – Qwertie
re no es serializable: sí, se producirá una excepción en el tiempo de ejecución. re arrays MBR: tiene el mismo problema que List, ya que array es la clase de nivel superior. –
El experimento muestra que un MBR no serializable dentro de un contenedor serializable se pasa por referencia sin excepción. –