【问题标题】:Serializing Lists of Classes to XML将类列表序列化为 XML
【发布时间】:2010-09-15 18:53:13
【问题描述】:

我有一组要序列化为 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&lt;Bar&gt;

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

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

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

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

【问题讨论】:

    标签: c# xml serialization


    【解决方案1】:
    var xmlfromLINQ = new XElement("BarList",
                from c in BarList 
                select new XElement("Bar",
                    new XElement("Property1", c.Property1),
                    new XElement("Property2", c.Property2)
                 ));
    

    【讨论】:

      【解决方案2】:

      自发布此项目以来已超过 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>
      

      我只花了两天时间就发现解决方案是省略 List(of T) 元素的 &lt;XmlElement&gt; 前缀。

      【讨论】:

      • 但问题是关于 C# - 而不是 VB
      • 从人类的角度来看,它们没有任何东西
      • @5arx 所以你的意思是一个专业的程序员无法想办法把 改成 [ ]?
      • @AdamHeeg 显然他/她可以,但也许有一定的难度“我花了两天时间......”。作为专业人士,我们都可以使用汇编语言进行编程,但我们可能宁愿不这样做。
      【解决方案3】:

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

      Foo

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

      【讨论】:

      【解决方案4】:

      只是检查一下,您是否将 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>
      

      【讨论】:

      • [Serializable] 未被 XML 序列化程序使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-08
      • 1970-01-01
      相关资源
      最近更新 更多