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;
}
}
}
目前我正在尝试将我的一些 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;
}
}
}