2010-07-02 22 views
6

Se si utilizza la serializzazione XML personalizzato (IXmlSerialiable), su un oggetto complesso che contiene gli oggetti con oggetti complessi costituenti che non NON usare personalizzato IXmlSerializable interfaccia, come si fa a specificare, nella IXmlSerializable.ReadXml(XmlReader reader) metodo, che vuoi che il deserializzatore usi la deserializzazione ordinaria su quelle proprietà figlio?Utilizzando l'interfaccia IXmlSerializable sul grafico oggetto complesso

NOTA: simile a this question

risposta

7

Il IXmlSerializable è un po 'noioso da implementare poiché è praticamente un approccio tutto o niente dato che non è possibile selezionare i tipi di bambino per il normale serializzazione XML. Tuttavia, se ho capito bene, puoi ottenere ciò che desideri creando manualmente XmlSerializer per i tipi che non implementano IXmlSerializable.

Ad esempio, se iniziamo con due classi, Default che non implementa IXmlSerializable e Custom che lo implementa.

public class Default // Uses default XML Serialization 
{ 
    public int Count { get; set; } 
} 

public class Custom : IXmlSerializable 
{ 
    public int Count { get; set; } 

    public XmlSchema GetSchema() { throw new NotImplementedException(); } 

    public void ReadXml(XmlReader reader) 
    { 
     reader.ReadToDescendant("Count"); 
     this.Count = reader.ReadElementContentAsInt(); 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteStartElement("Custom"); 
     writer.WriteElementString("Count", this.Count.ToString()); 
     writer.WriteEndElement(); 
    } 
} 

viene creato una terza classe Parent che ha un figlio di ciascuno dei casi precedenti e implementa IXmlSerializable in un modo che richiama ReadXml/WriteXml metodi per il bambino che lo sostiene e creare serializzatore XML di default per l'altro bambino.

public class Parent : IXmlSerializable 
{ 
    public Parent() 
    { 
     this.Default = new Default { Count = 1 }; 
     this.Custom = new Custom { Count = 2 }; 
    } 

    public Default Default { get; set; } 
    public Custom Custom { get; set; } 

    public XmlSchema GetSchema() { throw new NotImplementedException(); } 

    public void ReadXml(XmlReader reader) 
    { 
     reader.ReadToFollowing("Custom"); 
     this.Custom = new Custom(); 
     this.Custom.ReadXml(reader); 

     reader.ReadToFollowing("Default"); 
     var serializer = new XmlSerializer(typeof(Default)); 
     this.Default = (Default)serializer.Deserialize(reader); 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     this.Custom.WriteXml(writer); 

     var ns = new XmlSerializerNamespaces(); 
     ns.Add("", ""); 
     new XmlSerializer(typeof(Default)).Serialize(writer, this.Default, ns); 
    } 
} 

Per rendere l'esempio completo, un programma di esempio che serializza e deserializza un'istanza Parent:

static void Main() 
{ 
    var sb = new StringBuilder(); 
    var serializer = new XmlSerializer(typeof(Parent)); 

    serializer.Serialize(new StringWriter(sb), new Parent()); 

    Console.WriteLine(sb); 

    var parent = (Parent)serializer.Deserialize(new StringReader(sb.ToString())); 

    Console.WriteLine("Parent.Custom.Count: {0}", parent.Custom.Count); 
    Console.WriteLine("Parent.Default.Count: {0}", parent.Default.Count); 
} 
+0

Thx tanto ... sto per provare questo .. ma sembra sulla superficie per essere esattamente ciò di cui ho bisogno .. –

+1

Una piccola nota: è possibile utilizzare XmlSerializer sia per gli oggetti Predefinito che per quelli personalizzati nei metodi WriteXml()/ReadXml(). – synergetic

+0

Quando deserializzi un oggetto figlio passandolo a 'XmlReader', il puntatore del lettore finisce nel posto giusto (proprio alla fine dell'elemento figlio), o è ritardato? – toddmo

Problemi correlati