2010-02-22 6 views
11

Tengo una clase simple que está marcada como Serializable, y sucede que tiene un evento. Traté de marcar el miembro del evento como NonSerialized, sin embargo el compilador se queja. Sin embargo, cuando voy a serializar la instancia de clase, BinaryFormatter arroja una excepción que indica que el evento no es serializable. ¿Eso significa que no puedes serializar las clases que tienen eventos? Si es así, entonces el compilador debería decirlo así por adelantado.¿Por qué BinaryFormatter intenta serializar un evento en una clase serializable?

Stream file = File.Open("f", FileMode.Open); 
BinaryFormatter bf = new BinaryFormatter(); 

object obj = null; 
try 
{ 
    obj = bf.Deserialize(file); 
} 
catch (System.Runtime.Serialization.SerializationException e) 
{ 
    MessageBox.Show("De-Serialization failed : {0}", e.Message); 
} 
file.Close(); 

System.Collections.ArrayList nodeList = obj as System.Collections.ArrayList; 

foreach (TreeNode node in nodeList) 
{ 
    treeView.Nodes.Add(node); 
} 

no funciona con la clase siguiente:

[Serializable()] 
class Simple 
{ 
    private int myInt; 
    private string myString; 
    public event SomeOtherEventDefinedElsewhere TheEvent; 

}

+0

¿Puedes explicarnos un poco más sobre lo que intentas hacer y posiblemente darnos un pequeño fragmento de código? – IAbstract

+0

Claro. Acabo de tener esta clase que tiene principalmente propiedades string e int. Pero tiene algunos eventos para notificar a los consumidores cuando las instancias cambian. Estoy almacenando instancias de esta clase en la propiedad Tag de una clase .NET TreeView, o más específicamente, en cada propiedad Tag de cada TreeNode que corresponde al objeto.Cuando trato de serializar TreeView en el disco (almacenando cada nodo en una ArrayList y luego escribiendo la lista), obtengo una excepción: "Escriba 'MyEventSubscriber' en el ensamblado 'MyAssembly, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null 'no está marcado como serializable. " – Rhubarb

+0

cont ... MyEventSubscriber es la instancia de clase del suscriptor del evento en la clase que intento serializar (la que está en la propiedad Tag del TreeNode). – Rhubarb

Respuesta

19

"En el caso de eventos, también debe agregar el calificativo atributo de campo cuando aplicar el NonSerialized atributo para que el atributo se aplique a el delegado subyacente en lugar de a el evento en sí" Advanced Serialization - MSDN


Prefijo la NonSerializedAttribute con el campo

[field:NonSerialized] 
public event MyEventHandler MyEvent; 
+0

Lo intenté sin embargo no cambió nada. Todavía tengo la excepción. Sería muy extraño que no haya forma de disuadir al formateador de tratar de serializar esto. ¿Cualquier otra sugerencia? – Rhubarb

+0

funcionó para mí. ¡Gracias! No sabía acerca de la sintaxis '[field: Attribute]'. Me salvó algo de tipeo. – Max

0

Es importante recordar que el atributo se se aplica [Field:NonSerialized] a los delegados, no los eventos, entre mayúsculas y minúsculas por cierto, luego implemente un objeto ISerializable y, mediante el uso de la función de reflexión, repita la clase que está serializando, busque el controlador de eventos y anule la suscripción a los eventos antes de la serialización. Luego, al hacer la deserialización, puede cablear los eventos si es necesario automáticamente al deserializar ...

+2

¿Estás seguro? Parece que el campo debe estar en minúscula 'f'. ¿De qué sirve no serializar si tengo que ir y anular la suscripción a los eventos? – Rhubarb

+0

@ rhubarb @ Está liberando al delegado al recorrer la lista de oyentes que tienen los delegados o los eventos, si no 'el serializador volverá a aparecer a través de ellos ... – t0mm13b

+2

Bueno, ¿por qué tenemos que liberar a los oyentes si el evento es marcado como no serializable? ¿No es eso una contradicción? – Rhubarb

0

Sé que se trata de una publicación tardía, pero esta es una respuesta real a esta pregunta. Cree manualmente agregar/eliminar "getters/setters" para su evento (el compilador hace esto detrás de escena pero en este caso debe hacerlo explícitamente) y luego marque su evento como NonSerialized. No tengo tiempo para romper el código para usted, pero una búsqueda rápida revela a alguien que se encontró con el mismo problema:

http://sanity-free.org/113/csharp_binary_serialization_oddities.html

No utilice esta línea, sin embargo: [MethodImpl (MethodImplOptions.Synchronized)]

Esto genera problemas de seguridad de los hilos que se corrigieron en C# 4; ver:

http://blogs.msdn.com/b/cburrows/archive/2010/03/05/events-get-a-little-overhaul-in-c-4-part-i-locks.aspx

ya sea que usted necesita para rodar su propia alternativa lockless (con CAS) o buscar en línea para uno; Lamentablemente, no tengo tiempo, ya que tengo que correr, pero entiendes la idea.

Espero que esto ayude!

Cuestiones relacionadas