将作为ICollection <>导出的List <>序列化为XML

Pau*_*ulH 7 c# xml xml-serialization c#-3.0

我有一个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_; }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我像这样填充它:

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);
Run Code Online (Sandbox Code Playgroud)

然后像这样序列化它:

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);
}
Run Code Online (Sandbox Code Playgroud)

我得到一个看起来像这样的文件:

<Foo>
    <Something>My String</Something>
</Foo>
Run Code Online (Sandbox Code Playgroud)

但是,我想要的是XML,看起来像这样:

<Foo>
    <Something>My String</Something>
    <Bar>
        <!-- Data from first Bar -->
    </Bar>
    <Bar>
        <!-- Data from second Bar -->
    </Bar>
</Foo>
Run Code Online (Sandbox Code Playgroud)

我需要做什么才能让它List<>出现在XML中?

Eli*_*ing 3

要求XmlSerializer可序列化属性有一个设置器。除此之外,XmlSerializer不能序列化接口属性。以下代码将起作用:

[XmlElement("Bar")]
public List<Bar> Bars
{
    get { return bar_; }
    set { throw new NotSupportedException("This property 'Bars' cannot be set. This property is readonly."); }
}
Run Code Online (Sandbox Code Playgroud)

如果您不喜欢这个解决方案(例外有点难看),那么您可以实现IXmlSerializable并编写自己的自定义序列化。

编辑: Artur Mustafin 是对的,实现IEnumerableICollection 不需要 setter 的成员,如本 msdn 页面上所述:

XmlSerializer 对实现IEnumerable或 的类给予特殊处理ICollection。实现的类IEnumerable必须实现Add带有单个参数的公共方法。CurrentAdd 方法的参数必须与从返回值的属性返回的类型相同GetEnumerator,或者该类型的基之一。实现此外的类ICollection(例如 CollectionBase)必须IEnumerable具有Item采用整数的公共索引属性(C# 中的索引器),并且它必须具有Count整数类型的公共属性。该方法的参数Add必须与从属性返回的类型相同Item,或者该类型的基之一。对于实现 的类ICollection,要序列化的值是从索引Item属性中检索的,而不是通过调用GetEnumerator

  • 这是错误且丑陋的答案,这是错误的,因为它可以在没有设置器的情况下运行事件,请参阅我的帖子 (2认同)