2009-08-16 8 views
5

ho questa classe:DataContractSerializer non serializzazione membro della classe che eredita 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; } 
     } 
    } 
} 

perché eredita da HashSet deve attuare ISerializable, quindi il costruttore protetto e metodo GetObjectData. Precedentemente ho serializzato e deserializzato questa classe con successo con il BinaryFormatter.

Perché voglio essere in grado di ispezionare l'output generato dal serializzatore che voglio passare a DataContractSerializer.

Ho scritto questo test:

[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 prova non riesce perché la proprietà name è null! (i numeri interi sono (de) serializzati correttamente) Cosa sta succedendo?

MODIFICA: non ha nulla a che fare con il campo del nome che è privato. Rendendolo pubblico ha lo stesso risultato.

+0

Perché il serializzatore di contratto di dati serializza quello? Non ci sono attributi '[DataContract]' o '[DataMember]'. –

+0

@ John: ci ho provato ovviamente. Ma ho ottenuto un'eccezione affermando che: Digitare 'Grouping.Group'1 [[System.Int32, mscorlib, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089]]' non può essere ISerializable e avere attributo DataContractAttribute .. Ho pensato che DataContractSerializer sarebbe perfettamente soddisfatto delle classi contrassegnate con SerializableAttribute. – Dabblernl

+0

@John - DCS lo fa ora ... era puro "richiedo un contratto", ma ora ne inferirà anche uno mancante. Una corruzione, IMO. Funziona come BinaryFormatter - cioè guarda i ** campi **; che è abbastanza facilmente il modo peggiore che avrebbe potuto essere fatto. Ma non sono amaro –

risposta

5

Questo non ha nulla a che fare con ISerializable; DataContractSerializer fa semplicemente non usoISerializable (userà IXmlSerializable, ma non si vuole farlo ...)

La maggior parte dei serializzatori, tra cui XmlSerializer e DataContractSerializer (e di associazione dati, è per questo), tratta le raccolte come diverse dalle entità. Può essere uno o l'altro, ma non entrambi. Poiché rileva che si tratta di una "raccolta", serializza il contenuto (ad esempio qualsiasi cosa sia nell'insieme), non le proprietà (Name ecc.).

Si dovrebbe incapsulare una raccolta, piuttosto che ereditare esso.

Inoltre; per utilizzare correttamente DataContractSerializer, sarebbe opportuno aggiungere gli attributi [DataMember]/[DataContract]. Ad esempio:

+0

+1 buona spiegazione –

+0

Grazie, il contenuto dell'eredità la raccolta era effettivamente serializzata correttamente, ma non i membri della classe ereditaria. Regolerò il codice per dimostrarlo. – Dabblernl

Problemi correlati