19

我有一个简单的类,它继承自 Collection 并添加了几个属性。我需要将此类序列化为 XML,但 XMLSerializer 忽略了我的附加属性。

我认为这是因为 XMLSerializer 对 ICollection 和 IEnumerable 对象进行了特殊处理。解决这个问题的最佳方法是什么?

这是一些示例代码:

using System.Collections.ObjectModel;
using System.IO;
using System.Xml.Serialization;

namespace SerialiseCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            var c = new MyCollection();
            c.Add("Hello");
            c.Add("Goodbye");

            var serializer = new XmlSerializer(typeof(MyCollection));
            using (var writer = new StreamWriter("test.xml"))
                serializer.Serialize(writer, c);
        }
    }

    [XmlRoot("MyCollection")]
    public class MyCollection : Collection<string>
    {
        [XmlAttribute()]
        public string MyAttribute { get; set; }

        public MyCollection()
        {
            this.MyAttribute = "SerializeThis";
        }
    }
}

这将输出以下 XML(注意 MyCollection 元素中缺少 MyAttribute):

<?xml version="1.0" encoding="utf-8"?>
<MyCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <string>Hello</string>
    <string>Goodbye</string>
</MyCollection>

想要的是

<MyCollection MyAttribute="SerializeThis" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <string>Hello</string>
    <string>Goodbye</string>
</MyCollection>

有任何想法吗?越简单越好。谢谢。

4

5 回答 5

16

集合通常不会成为额外属性的好地方。在序列化和数据绑定期间,如果项目看起来像一个集合( , 等 - 取决于场景),它们将被IList忽略IEnumerable

如果是我,我会封装这个集合——即

[Serializable]
public class MyCollectionWrapper {
    [XmlAttribute]
    public string SomeProp {get;set;} // custom props etc
    [XmlAttribute]
    public int SomeOtherProp {get;set;} // custom props etc
    public Collection<string> Items {get;set;} // the items
}

另一种选择是实现IXmlSerializable(相当多的工作),但这仍然不适用于数据绑定等。基本上,这不是预期的用法。

于 2008-12-18T10:43:20.560 回答
13

如果您确实按照 Marc Gravell 的建议进行封装,那么本文开头将解释如何让您的 XML 看起来与您描述的完全一样。

http://blogs.msdn.com/youssefm/archive/2009/06/12/customizing-the-xml-for-collections-with-xmlserializer-and-datacontractserializer.aspx

也就是说,而不是这样:

<MyCollection MyAttribute="SerializeThis" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Items>
    <string>Hello</string>
    <string>Goodbye</string>
  <Items>
</MyCollection>

你可以有这个:

<MyCollection MyAttribute="SerializeThis" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">      
  <string>Hello</string>
  <string>Goodbye</string>
</MyCollection>
于 2010-03-25T19:07:54.793 回答
3

正如 Neil Whitaker 所建议的那样,以防他的链接失效。

创建一个内部集合来存储字符串并应用 XmlElement 属性来屏蔽集合名称。生成与从 Collection 继承的 MyCollection 相同的 xml 输出,但还会序列化父元素上的属性。

[XmlRoot("MyCollection")]
public class MyCollection 
{
    [XmlAttribute()]
    public string MyAttribute { get; set; }

    [XmlElement("string")]
    public Collection<string> unserializedCollectionName { get; set; }

    public MyCollection()
    {
        this.MyAttribute = "SerializeThis";
        this.unserializedCollectionName = new Collection<string>();
        this.unserializedCollectionName.Add("Hello");
        this.unserializedCollectionName.Add("Goodbye");
    }
}
于 2015-02-16T13:39:48.883 回答
0

我一直在与 Romaroo 的相同问题作斗争(想要将属性添加到实现 ICollection 的类的 xml 序列化中)。我还没有找到任何方法来公开集合类中的属性。我什至尝试使用 XmlAttribute 标记并使我的属性显示为根节点的属性,但也没有运气。但是,我能够在我的班级上使用 XmlRoot 标记将其从“ArrayOf ...”重命名。如果您有兴趣,这里有一些参考资料:

于 2008-12-30T14:42:22.357 回答
0

有时你只想做你想做的事;该框架该死。

我在这里发布了一个答案List<T> Not Deserialized 的属性

这就是OP想要做的。

于 2015-01-24T22:45:13.980 回答