XML (反)列表序列化

XML (De)Serialization of List

目前我正在尝试将我的一些 classes 序列化和反序列化为 XML。一种方式 (List -> XML) 完美地工作(见下面的例子)。另一种方式将无法正常工作。 我不想反序列化的 class 本身包含另一个 class 的列表。这在 XML 文件中也是正确的。但是当我反序列化 class 时,它不起作用。

在下面的例子中,这意味着 class Foo 被正确地序列化为它的 Bars 列表。但是当我反序列化 XML-File 时,只有 FooString 和其他属性得到正确序列化。酒吧列表每次都是空的。调试器也不会随时到达那里。

谁能告诉我我做错了什么?

提前致谢!

主要对象如下所示:

[XmlInclude(typeof (Bar))]
[XmlRoot(ElementName = "Foo")]
public class Foo()  : IFooInterface
{
    [XmlElement("FooString")]
    public string FooString
    {
        // For simplifaction auto proerty, normally with
        // backing field
        get;
        set;
    }

    // Some other properties for the xml
    // ...

    // Dirty Hack to serialize the List, because an Interface could not be serialized
    // I've already tried to remove this tag, to replace it with [XmlElement("BarList")], but nothing works
    [XmlArray("BarList")]
    [XmlArrayItem(ElementName = "Bar", Type = typeof(Bar))]
    public List<Bar> XmlBarList
    {
        get
        {
            return this.BarList.Select(bar => bar as Bar).ToList();
        }
        set
        {
            this.BarList = new ObservableCollection<IBarInterface>(value);
        }
    }

    private ObservableCollection<IBarInterface> barList;

    [XmlIgnore]
    public ObservableCollection<IBarInterface> BarList
    {
        get
        {
            return this.barList;
        }
        set
        {
            // For simplification removed Notification Proerties
            this.barList = value;
        }
    }
}

嵌套的 class 看起来像这样:

[XmlType("Bar")]
public class Bar : IBarInterface
{
    [XmlElement("BarString")]
    public string BarString
    {
        get;
        set;
    }

    // Some other properties for the xml 
    // ...
}

class 序列化 classes:

public class FooBarProvider()
{
    // Won't work
    // the BarList of any Foo item is everytime
    // empty. 
    public List<Foo> Load()
    {
        var reader = new StreamReader("PathToTheXml.xml");
        var serializer = new XmlSerializer(typeof(List<Foo>));
        var list = (List<Foo>)serializer.Deserialize(reader);
    }

    // Works
    public void Save(List<Foo> fooList)
    {
       var serializer = new XmlSerializer(typeof(List<Foo>));
       var writer = new StreamWriter("PathToTheXml.xml");
       serializer.Serialize(writer, fooList);
       writer.Close();
    }
}

生成的XML文件:

<ArrayOfFoo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Foo>
    <BarList>
      <Bar>
        <BarString>Hello Bar!</BarString>
      </Bar>
    </BarList>
    <FooString>Hello Foo!</FooString>
  </Foo>
</ArrayOfFoo>

不要使用 XmlArray。它创建了一组额外的节点。请改用 XmlElement。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {

            ArrayOfFoo aof = new ArrayOfFoo() {
                foo = new Foo() {
                     FooString = "Hello Foo!",
                     barList = new List<BarList>() {
                        new BarList() {
                          bar = new Bar() {
                              barString = "Hello Bar!"
                          }
                        }
                     }
                }
            };

            XmlSerializer serializer = new XmlSerializer(typeof(ArrayOfFoo));

            StreamWriter writer = new StreamWriter(FILENAME);
            serializer.Serialize(writer, aof);
            writer.Flush();
            writer.Close();
            writer.Dispose();

            XmlSerializer xs = new XmlSerializer(typeof(ArrayOfFoo));
            XmlTextReader reader = new XmlTextReader(FILENAME);
            ArrayOfFoo newAof = (ArrayOfFoo)xs.Deserialize(reader);
        }
    }
    [XmlRoot(ElementName = "ArrayOfFoo")]
    public class ArrayOfFoo
    {
        [XmlElement("Foo")]
        public Foo foo { get; set; }
    }

     [XmlRoot(ElementName = "Foo")]
    public class Foo
    {
        [XmlElement("FooString")]
        public string FooString { get; set; }


        [XmlElement("BarList")]
        public List<BarList> barList { get; set; }

    }


    [XmlRoot(ElementName = "BarList")]
    public class BarList
    {
        [XmlElement("Bar")]
        public Bar bar { get; set; }
    }


    [XmlRoot(ElementName = "Bar")]
    public class Bar
    {
        [XmlElement("BarString")]
        public string barString { get; set; }
    }
    [XmlRoot(ElementName = "BarString")]
    public class BarString
    {
        [XmlText]
        public string value { get; set; }
    }​
}
​

该死的!

我明白我的错误了。

通过我的脏 ​​"hack" 序列化接口对象,它将创建一个临时对象。 XmlSerializer 获取临时对象并将数据存储在那里。

是否有任何其他序列化和反序列化接口的解决方案?在 class Foo 中,我知道它是 bar 的一个实例。但是接口迫使我实现一个 IBarInterface 列表。

Foo的界面:

public interface IFooInterface
{
    ObservableCollection<IBarInterface> BarList { get; }
}

IFooInterface的实现:

[XmlInclude(typeof(Bar))]
[XmlRoot(ElementName ="Foo")]
public class Foo : IFooInterface
{
    ObservableCollection<IBarInterface> barList;

    [XmlElement(ElementName ="BarList")]
    public ObservableCollection<Bar> XmlBarList
    {
        get
        {
            // Creates an temporary Object, so it won't work
            return this.BarList.Select(bar => bar as Bar).ToList();
        }
        set
        {
             this.BarList = new ObservableCollection<IBarInterface>(value);
        }
    }

    // Won't work out of the box with XmlSerializer
    // so I Ignore it
    [XmlIgnore]
    ObservableCollection<IBarInterface> BarList
    {
        get
        {
            return this.barList;
        }
        set
        {
            this.barList = value;
        }
    }
}

Bar的界面:

public interface IBarInterface
{
    string BarString { get; }
}

IBarInterface的实现:

[XmlRoot(ElementName ="Bar")]
public class Bar : IBarInterface
{
    string BarString;

    [XmlElement(ElementName = "BarString")]
    string BarString
    {
        get
        {
            return this.bar;
        }
        set
        {
            this.bar = value;
        }
    }
}