35

我有一组要序列化为 XML 文件的类。它看起来像这样:

public class Foo
{
  public List<Bar> BarList { get; set; }
}

bar 只是属性集合的包装器,如下所示:

public class Bar
{
  public string Property1 { get; set; }
  public string Property2 { get; set; }
}

我想标记它,以便它输出到一个 XML 文件 - 这将用于持久性,也可以通过 XSLT 将设置呈现为一个很好的人类可读形式。

我想得到一个很好的 XML 表示,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Foo>
  <BarList>
    <Bar>
      <Property1>Value</Property1>
      <Property2>Value</Property2>   
    </Bar>
    <Bar>
      <Property1>Value</Property1>
      <Property2>Value</Property2>   
    </Bar>
  </Barlist>
</Foo>

Barlist 中的所有 Bars 都在哪里写出了它们的所有属性。我相当确定我需要对类定义进行一些标记才能使其工作,但我似乎找不到正确的组合。

我已经用属性标记了 Foo

[XmlRoot("Foo")]  

list<Bar>带有属性的

[XmlArray("BarList"), XmlArrayItem(typeof(Bar), ElementName="Bar")]

试图告诉序列化器我想要发生什么。但是,这似乎不起作用,我只得到一个空标签,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Foo> 
  <Barlist />
</Foo>

我不确定我使用自动属性的事实是否应该有任何影响,或者使用泛型是否需要任何特殊处理。我已经让它与更简单的类型(如字符串列表)一起使用,但到目前为止我还没有找到类列表。

4

4 回答 4

31

只是检查一下,您是否将 Bar 标记为 [Serializable]?

此外,您需要在 Bar 上使用无参数 ctor 来反序列化

嗯,我用过:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {

        Foo f = new Foo();

        f.BarList = new List<Bar>();

        f.BarList.Add(new Bar { Property1 = "abc", Property2 = "def" });

        XmlSerializer ser = new XmlSerializer(typeof(Foo));

        using (FileStream fs = new FileStream(@"c:\sertest.xml", FileMode.Create))
        {
            ser.Serialize(fs, f);
        }
    }
}

public class Foo
{
    [XmlArray("BarList"), XmlArrayItem(typeof(Bar), ElementName = "Bar")]
    public List<Bar> BarList { get; set; }
}

[XmlRoot("Foo")]
public class Bar
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

这产生了:

<?xml version="1.0"?>
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <BarList>
    <Bar>
      <Property1>abc</Property1>
      <Property2>def</Property2>
    </Bar>
  </BarList>
</Foo>
于 2008-10-07T15:10:14.540 回答
4

一切看起来都很棒。正如@Carl 所说,您需要将[Serializable]属性添加到您的类中,但除此之外,您的 XML 创建应该可以找到。

[Serializable]
[XmlRoot("Foo")]
public class Foo
{
    [XmlArray("BarList"), XmlArrayItem(typeof(Bar), ElementName = "Bar")]
    public List<Bar> BarList { get; set; }
}

酒吧

[Serializable]
public class Bar
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

测试代码

Foo f = new Foo();
f.BarList = new List<Bar>();
f.BarList.Add(new Bar() { Property1 = "s", Property2 = "2" });
f.BarList.Add(new Bar() { Property1 = "s", Property2 = "2" });

FileStream fs = new FileStream("c:\\test.xml", FileMode.OpenOrCreate);
System.Xml.Serialization.XmlSerializer s = new System.Xml.Serialization.XmlSerializer(typeof(Foo));
s.Serialize(fs, f);

输出

<?xml version="1.0" ?> 
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <BarList>
        <Bar>
            <Property1>s</Property1> 
            <Property2>2</Property2> 
        </Bar>
        <Bar>
            <Property1>s</Property1> 
            <Property2>2</Property2> 
        </Bar>
    </BarList>
</Foo>
于 2008-10-07T15:20:54.097 回答
2
var xmlfromLINQ = new XElement("BarList",
            from c in BarList 
            select new XElement("Bar",
                new XElement("Property1", c.Property1),
                new XElement("Property2", c.Property2)
             ));
于 2017-11-10T04:59:36.480 回答
1

自发布此项目以来已经超过 5 年。我从 2013 年 7 月(.NET Framework 4.5)开始提供我的经验。对于它的价值和可能涉及的对象:

当我像这样定义一个类时:(VB.Net代码)

<Serializable> Public Class MyClass
    Public Property Children as List(of ChildCLass)
    <XmlAttribute> Public Property MyFirstProperty as string
    <XmlAttribute> Public Property MySecondProperty as string
End Class

<Serializable> Public Class ChildClass
    <XmlAttribute> Public Property MyFirstProperty as string
    <XmlAttribute> Public Property MySecondProperty as string
End Class

使用此定义,该类被(反)序列化而没有任何问题。这是来自这里的 XML:

<MyClass> MyFirstProperty="" MySecondProperty=""
    <Children>
        <ChildClass> MyFirstProperty="" MySecondProperty=""
        </ChildClass>
   </Children>
</MyClass>

我只花了两天时间就弄清楚解决方案是省略<XmlElement>List(of T) 元素的前缀。

于 2013-07-31T20:49:55.937 回答