2010-07-02 12 views
6

Si se utiliza la serialización XML personalizado (IXmlSerialiable), en un objeto complejo que contiene propiedades con objetos complejos constituyentes que hacen NO usar encargo IXmlSerializable interfaz, ¿cómo se especifique, en el IXmlSerializable.ReadXml(XmlReader reader) método, ¿quiere que el deserializador use la deserialización ordinaria en esas propiedades secundarias?Usando la interfaz IXmlSerializable el gráfico de objetos complejos

NOTA: similar a this question

Respuesta

7

El IXmlSerializable es un poco tedioso para poner en práctica, ya que es más o menos un enfoque de todo o nada teniendo en cuenta que no se puede seleccionar tipos de niños para la serialización XML normal. Sin embargo, si te entendí correctamente, puedes lograr lo que deseas creando manualmente XmlSerializer para los tipos que no implementan IXmlSerializable. Por ejemplo, si comenzamos con dos clases, Default que no implementa IXmlSerializable y Custom que sí 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(); 
    } 
} 

entonces se crea una tercera clase Parent que tiene un niño de cada uno de los casos anteriores e implementa IXmlSerializable de una manera que llama ReadXml/WriteXml métodos para el niño que lo soporta y crear serializador XML por defecto para el otro niño.

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); 
    } 
} 

Para hacer el ejemplo completo, un programa de ejemplo que serializa y deserializa un Parent ejemplo:

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 ... que voy a probar este .. pero parece que en la superficie para ser exactamente lo que necesito. –

+1

Una pequeña nota: Puede usar XmlSerializer para objetos predeterminados y personalizados en los métodos WriteXml()/ReadXml(). – synergetic

+0

Cuando deserializa un objeto secundario entregándole el 'XmlReader', ¿el puntero del lector termina en el lugar correcto (justo al final del elemento hijo) o se retarda? – toddmo

Cuestiones relacionadas