C # Xml Serializing List <T>потомок с атрибутом Xml - PullRequest
13 голосов
/ 05 августа 2010

Morning Guys,

У меня есть коллекция, которая происходит из списка и имеет публичную собственность.Сериализатор Xml не забирает мой proeprty.Элементы списка сериализуются нормально.Я пробовал атрибут XmlAttribute безрезультатно.Ребята, у вас есть решение?

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

Я получаю следующее 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>

Я хотел бы получить это

<?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>

Ответы [ 3 ]

4 голосов
/ 06 августа 2010

Это не ответ на вопрос, но я подумал, что хотел бы предложить облегчить разработку кода.

Добавить новый метод Add в класс PersonCollection следующим образом:

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

Затем, выполнив это, вы можете упростить синтаксис инициализатора коллекции до:

var people = new PersonCollection
{
    { "Sue", 17 },
    { "Joe", 21 }
};
people.FavoritePerson = "Sue";
4 голосов
/ 05 августа 2010

Я решил проблему, внедрив IXmlSerializable. Если существует более простое решение, опубликуйте его!

    [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();            
        }
    }
}
1 голос
/ 16 сентября 2011

Если вы не возражаете против того, чтобы обернуть все функции списка, вы можете встраивать список как свойство класса, а не как его производное.

Затем вы бы использовали атрибут XmlElement, чтобы заставить элементы xml быть записанными в виде плоского списка (а не вложенного).

...