我有一个C#.NET 3.5应用程序,我想将包含List<>
的类序列化为XML。我的班级看起来像这样:
[XmlRoot("Foo")]
class Foo
{
private List<Bar> bar_ = new List<Bar>();
private string something_ = "My String";
[XmlElement("Something")]
public string Something { get { return something_; } }
[XmlElement("Bar")]
public ICollection<Bar> Bars
{
get { return bar_; }
}
}
如果我这样填充它:
Bar b1 = new Bar();
// populate b1 with interesting data
Bar b2 = new Bar();
// populate b2 with interesting data
Foo f = new Foo();
f.Bars.Add(b1);
f.Bars.Add(b2);
然后将其序列化为:
using (System.IO.TextWriter textWriter = new System.IO.StreamWriter(@"C:\foo.xml"))
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Foo));
serializer.Serialize(textWriter, f);
}
我得到一个看起来像这样的文件:
<Foo>
<Something>My String</Something>
</Foo>
但是,我想要的是XML,看起来像这样:
<Foo>
<Something>My String</Something>
<Bar>
<!-- Data from first Bar -->
</Bar>
<Bar>
<!-- Data from second Bar -->
</Bar>
</Foo>
我需要做些什么才能让List<>
出现在XML中?
答案 0 :(得分:3)
XmlSerializer
要求可序列化属性具有setter。除此之外,XmlSerializer
无法序列化接口属性。以下代码将起作用:
[XmlElement("Bar")]
public List<Bar> Bars
{
get { return bar_; }
set { throw new NotSupportedException("This property 'Bars' cannot be set. This property is readonly."); }
}
如果您不喜欢这个解决方案(异常有点难看),那么您可以实现IXmlSerializable
并编写自己的自定义序列化。
修改:Artur Mustafin是对的,实施IEnumerable
或ICollection
的成员不需要setter ,如{ {3}}:
XmlSerializer为实现
IEnumerable
或ICollection
的类提供特殊处理。实现IEnumerable
的类必须实现采用单个参数的公共Add
方法。 Add方法的参数必须与从Current
返回的值GetEnumerator
属性返回的类型相同,或者是该类型的基础之一。除了ICollection
之外,实现IEnumerable
的类(例如CollectionBase)必须具有公共Item
索引属性(C#中的索引器),它采用整数,并且必须具有公共{ {1}}整数类型的属性。Count
方法的参数必须与从Add
属性返回的类型相同,或者是该类型的基础之一。对于实现Item
的类,要从序列化的ICollection
属性中检索要序列化的值,而不是通过调用Item
。
答案 1 :(得分:3)
给出正确的答案,没有必要为List<T>
公共属性创建丑陋的setter,抛出异常。
这是因为List<>
已经实现ICollection<T>
并提供了序列化机制使用的签名void Add(T object)
的方法;
您只需将setter添加到要序列化的公共属性,并将ICollection<T>
更改为List<T>
:
[XmlRoot("Foo")]
public class Foo
{
private List<Bar> bar_ = new List<Bar>();
[XmlElement("Something")]
public string Something { get; set; }
[XmlElement("Bar")]
public List<Bar> Bars { get { return bar_; } }
}
您将获得输出:
<?xml version="1.0" encoding="utf-8"?>
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Something>My String</Something>
<Bar />
<Bar />
</Foo>
此外,最好在内存中序列化xml,查看结果或测试它,如下所示:
static void Main(string[] args)
{
Bar b1 = new Bar();
// populate b1 with interesting data
Bar b2 = new Bar();
// populate b2 with interesting data
Foo f = new Foo();
f.Bars.Add(b1);
f.Bars.Add(b2);
f.Something = "My String";
using (MemoryStream ms = new MemoryStream())
using (System.IO.TextWriter textWriter = new System.IO.StreamWriter(ms))
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Foo));
serializer.Serialize(textWriter, f);
string text = Encoding.UTF8.GetString(ms.ToArray());
Console.WriteLine(text);
}
Console.ReadKey(false);
}
要使用接口序列化,请使用我的项目XmlSerialization