列表

时间:2015-07-11 18:05:55

标签: c# xml-serialization xmlserializer

目前我正在尝试将我的一些类序列化和反序列化为XML。单向(List - > XML)完美运行(参见下面的示例)。另一种方式不能正常工作。 我要反序列化的类包含另一个类的另一个List。这在XML文件中也是正确的。但是当我对课程进行反序列化时,它不会起作用。

在下面的示例中,这意味着类Foo使用其List列表正确序列化。但是,当我反序列化XML-File时,只有FooString,其他属性才能正确序列化。 Bar列表每次都是空的。调试器也无法随时到达那里。

有人能告诉我我做错了吗?

提前致谢!

主要对象如下所示:

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

嵌套类如下所示:

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

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

(de)序列化类的类:

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>

2 个答案:

答案 0 :(得分:0)

不要使用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; }
    }​
}
​

答案 1 :(得分:0)

哦,该死的!

我看到了我的错误。

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

是否有其他解决方案来序列化和反序列化接口?在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;
        }
    }
}