2010-08-05 13 views
12

Guys mañana,C#, XML Lista Serializar <T> descendiente con el atributo xml

Tengo una colección que desciende de la lista y tiene una propiedad pública. El serializador Xml no recoge mi propiedad. Los elementos de la lista se serializan bien. He intentado el atributo XmlAttribute en vano. ¿Ustedes tienen una solución?

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 
    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     var people = new PersonCollection 
     { 
      new Person { FirstName="Sue", Age=17 }, 
      new Person { FirstName="Joe", Age=21 } 
     }; 
     people.FavoritePerson = "Sue"; 

     var x = new XmlSerializer(people.GetType()); 
     var b = new StringBuilder(); 
     var w = XmlTextWriter.Create(b, new XmlWriterSettings { NewLineChars = "\r\n", Indent = true }); 
     x.Serialize(w, people); 
     var s = b.ToString(); 
    } 
} 

[XmlRoot(ElementName="People")] 
public class PersonCollection : List<Person> 
{ 
    //DOES NOT WORK! ARGHHH 
    [XmlAttribute] 
    public string FavoritePerson { get; set; }  
} 

public class Person 
{ 
    [XmlAttribute] 
    public string FirstName { get; set; } 
    [XmlAttribute] 
    public int Age { get; set; } 
} 

Estoy recibiendo el siguiente código XML

<?xml version="1.0" encoding="utf-16"?> 
     <People xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
      <Person FirstName="Sue" Age="17" /> 
      <Person FirstName="Joe" Age="21" /> 
     </People> 

me gustaría conseguir este

<?xml version="1.0" encoding="utf-16"?> 
     <People FavoritePerson="Sue" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
      <Person FirstName="Sue" Age="17" /> 
      <Person FirstName="Joe" Age="21" /> 
     </People> 

Respuesta

4

seguí adelante y resuelto el problema mediante la implementación de IXmlSerializable. Si existe una solución más simple, ¡publícala!

[XmlRoot(ElementName="People")] 
public class PersonCollection : List<Person>, IXmlSerializable 
{ 
    //IT WORKS NOW!!! Too bad we have to implement IXmlSerializable 
    [XmlAttribute] 
    public string FavoritePerson { get; set; } 

    public System.Xml.Schema.XmlSchema GetSchema() 
    { 
     return null; 
    } 
    public void ReadXml(XmlReader reader) 
    { 
     FavoritePerson = reader[0];    
     while (reader.Read()) 
     { 
      if (reader.Name == "Person") 
      { 
       var p = new Person(); 
       p.FirstName = reader[0]; 
       p.Age = int.Parse(reader[1]); 
       Add(p); 
      } 
     } 
    } 
    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteAttributeString("FavoritePerson", FavoritePerson); 
     foreach (var p in this) 
     { 
      writer.WriteStartElement("Person"); 
      writer.WriteAttributeString("FirstName", p.FirstName); 
      writer.WriteAttributeString("Age", p.Age.ToString()); 
      writer.WriteEndElement();    
     } 
    } 
} 
+0

Steve puede aceptar sus propias respuestas. – nawfal

4

Esta no es una respuesta a la pregunta, pero pensé que haría una sugerencia para facilitar el desarrollo del código.

Añadir un nuevo método Add a la clase PersonCollection como tal:

public class PersonCollection : List<Person>, IXmlSerializable 
{ 
... 
    public void Add(string firstName, int age) 
    { 
     this.Add(new Person(firstName, age)); 
    } 
... 
} 

Entonces, al hacer esto, puede simplificar la sintaxis de inicializador de colección a:

var people = new PersonCollection 
{ 
    { "Sue", 17 }, 
    { "Joe", 21 } 
}; 
people.FavoritePerson = "Sue"; 
+0

Buen truco. ¡Gracias! – Steve

1

Si no lo hace Tendrá que ajustar todas las funciones de la lista, luego puede insertar la lista como una propiedad de la clase en lugar de derivar de ella.

Luego, usaría el atributo XmlElement para forzar que los elementos xml se escriban como una lista plana (en lugar de estar anidados).

Cuestiones relacionadas