2009-08-16 9 views
5

no Serializar tengo esta clase:DataContractSerializer miembro de la clase que hereda ISerializable

using System; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 

namespace Grouping 
{ 
    [Serializable] 
    public class Group<T> : HashSet<T> 
    { 
     public Group(string name) 
     { 
      this.name = name; 
     } 

     protected Group(){} 

     protected Group(SerializationInfo info, StreamingContext context):base(info,context) 
     { 
      name = info.GetString("koosnaampje"); 
     } 

     public override void GetObjectData(SerializationInfo info,StreamingContext context) 
     { 
      base.GetObjectData(info,context); 
      info.AddValue("koosnaampje", Name); 
     } 

     private string name; 
     public string Name 
     { 
      get { return name; } 
      private set { name = value; } 
     } 
    } 
} 

ya que hereda de HashSet tiene que implementar ISerializable, de ahí el constructor protegido y método GetObjectData. Anteriormente serialicé y deserialicé esta clase con éxito con BinaryFormatter.

Como deseo poder inspeccionar la salida generada por el serializador, deseo cambiar al DataContractSerializer.

escribí esta prueba:

[TestMethod] 
public void SerializeTest() 
{ 
    var group = new Group<int>("ints"){1,2,3}; 
    var serializer = new DataContractSerializer(typeof (Group<int>)); 
    using (var stream=File.OpenWrite("group1.xml")) 
    { 
     serializer.WriteObject(stream,group); 
    } 
    using (var stream=File.OpenRead("group1.xml")) 
    { 
     group = serializer.ReadObject(stream) as Group<int>; 
    } 
    Assert.IsTrue(group.Contains(1)); 
    Assert.AreEqual("ints",group.Name); 
} 

la prueba falla debido a que la propiedad Name es nulo! (los enteros son (de) serializados correctamente) ¿Qué está pasando?

EDITAR: no tiene nada que ver con que el campo de respaldo de nombre sea privado. Hacerlo público tiene el mismo resultado.

+0

¿Por qué el serializador de contrato de datos serializaría eso? No hay atributos '[DataContract]' o '[DataMember]'. –

+0

@John: lo probé, por supuesto. Pero recibí una excepción que indica que: Escriba 'Grouping.Group'1 [[System.Int32, mscorlib, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089]]' no puede ser ISerializable y tiene el atributo DataContractAttribute ... Pensé que el DataContractSerializer sería perfectamente feliz con las clases que están marcadas con SerializableAttribute. – Dabblernl

+0

@John - DCS sí lo hace ahora ... solía ser puro "exijo un contrato", pero ahora también se deducirá uno si falta. Una corrupción, IMO. Funciona como BinaryFormatter, es decir, mira los ** campos **; que es, con bastante facilidad, la peor manera posible en que podría haberse hecho. Pero no estoy amargado. –

Respuesta

5

Esto no tiene nada que ver con ISerializable; DataContractSerializer simplemente no usoISerializable (que utilizará IXmlSerializable, pero no quiero hacer eso ...)

La mayoría de los serializadores, incluyendo XmlSerializer y DataContractSerializer (y enlace de datos, para el caso), tratar las colecciones como diferentes a las entidades. Puede ser uno o el otro, pero no ambos. Como detecta que se trata de una "colección", serializa el contenido (es decir, lo que sea que esté en el conjunto), no las propiedades (Name, etc.).

Debe encapsular una colección, en lugar de heredar ella.

También; para usar correctamente DataContractSerializer, sería conveniente agregar los atributos [DataMember]/[DataContract]. Por ejemplo:

[Serializable, DataContract] // probably don't need [Serializable] 
public class Group<T> 
{ 
    [DataMember] 
    public HashSet<T> Items { get; private set; } 

    protected Group() 
    { 
     Items = new HashSet<T>(); 
    } 
    public Group(string name) : this() 
    { 
     Name = name; 
    } 
    [DataMember] 
    public string Name {get ;private set;} 
} 
+0

+1 buena explicación –

+0

Gracias, el contenido de la herencia la colección de hecho estaba correctamente serializada, pero no los miembros de la clase heredera. Ajustaré el código para mostrar eso. – Dabblernl

Cuestiones relacionadas