2009-03-01 7 views
16

Me gustaría usar un objeto en AppDomains.Utilice el atributo [Serializable] o la creación de subclases de MarshalByRefObject?

Para esto se puede utilizar el atributo [Serializeable]:

[Serializable] 
class MyClass 
{ 
    public string GetSomeString() { return "someString" } 
} 

o subclase de MarshalByRefObject:

class MyClass: MarshalByRefObject 
{ 
    public string GetSomeString() { return "someString" } 
} 

En ambos casos puedo utilizar la clase como esta:

AppDomain appDomain = AppDomain.CreateDomain("AppDomain"); 
MyClass myObject = (MyClass)appDomain.CreateInstanceAndUnwrap(
        typeof(MyClass).Assembly.FullName, 
        typeof(MyClass).FullName); 
Console.WriteLine(myObject.GetSomeString()); 

¿Por qué ambos enfoques parecen tener el mismo efecto? ¿Cuál es la diferencia en ambos enfoques? ¿Cuándo debería favorecer el enfoque sobre el otro?

EDIT: En la superficie, sé que hay diferencias entre ambos mecanismos, pero si alguien salta de un arbusto y me hace la pregunta, no podría darle una respuesta adecuada. Las preguntas son preguntas bastante abiertas. Esperaba que alguien pudiera explicarlo mejor de lo que podía hacerlo.

Respuesta

20

Usando MarshallByRef ejecutará sus métodos en el AppDomain remoto. Cuando utiliza CreateInstanceAndUnwrap con un objeto serializable, se realiza una copia del objeto al dominio de aplicación local, por lo que cualquier llamada a método se ejecutará en el dominio de aplicación local.

Si lo que desea es comunicarse entre AppDomains vaya con el enfoque MarshallByRef.

Un ejemplo:

using System; 
using System.Reflection; 

[Serializable] 
public class SerializableClass 
{ 
    public string WhatIsMyAppDomain() 
    { 
     return AppDomain.CurrentDomain.FriendlyName; 
    } 
} 

public class MarshallByRefClass : MarshalByRefObject 
{ 
    public string WhatIsMyAppDomain() 
    { 
     return AppDomain.CurrentDomain.FriendlyName; 
    } 
}  

class Test 
{ 

    static void Main(string[] args) 
    { 
     AppDomain ad = AppDomain.CreateDomain("OtherAppDomain"); 

     MarshallByRefClass marshall = (MarshallByRefClass)ad.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "MarshallByRefClass"); 
     SerializableClass serializable = (SerializableClass)ad.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "SerializableClass"); 

     Console.WriteLine(marshall.WhatIsMyAppDomain()); 
     Console.WriteLine(serializable.WhatIsMyAppDomain()); 

    } 
} 

Este código mostrará "OtherAppDomain" cuando se llama WhatIsMyAppDomain del objeto MarshallByRef, y su nombre de dominio de aplicación por defecto cuando se llama desde el objeto Serializable.

5

¿Por qué ambas aproximaciones tienen el mismo efecto?

Lo hacen no tienen el mismo efecto.

Con MarshalByRefObject está haciendo referencia a un objeto a través de los límites de AppDomain. Con [Serializable] se está haciendo una copia del objeto. Esto se mostrará si el estado del objeto se modifica en el dominio secundario y luego se examina de nuevo (o ejecuta el Console.WriteLine dentro del dominio de aplicación hijo).

+0

Ok ... han cambiado la pregunta. Parece * ya que ambos enfoques tienen el mismo efecto. –

2

MarshalByRefValue y Serializable implementan semántica diferente para comunicación remota/cruzada AppDomain. MarshalByRefValue esencialmente le da semántica de referencia a través de un objeto proxy, mientras que Serializable le da semántica de valores (es decir, el estado del objeto se copia).

En otras palabras MarshalByRefValue le permitirá modificar la instancia en diferentes AppDomains, mientras que Serializable no lo hará. Esto último es útil cuando solo necesita obtener la información de un dominio de aplicación a otro, p. para obtener el contenido de una excepción de un AppDomain a otro.

+1

Por favor deje un comentario cuando baje la votación. Gracias. –

9

Estos enfoques tienen efectos dramáticamente diferentes.

Con la versión MarshalByRef está creando 1 instancia de su objeto. Vivirá en el AppDomain recién creado. Todos los accesos al objeto se realizan a través de TransparentProxy.

Con la versión Serializable se crearán 2 instancias de su objeto. Uno se crea en el AppDomain recién creado. La llamada CreateInstanceAndUnwrap serializará este objeto y lo deserializará en el dominio de la aplicación original. Esto crea una segunda versión del objeto que es completamente independiente de la primera. De hecho, el próximo GC casi seguramente eliminará el objeto original y te quedará con una instancia.

+0

+1 para el enlace a la entrada fascinante del blog sobre TransparentProxy. Ese artículo realmente desmitifica MarshalByRefObject (MBRO) para mí. Ahora me pregunto qué diablos es Context y ContextBoundObject :) – Qwertie

Cuestiones relacionadas