XmlSerialize具有Attribute的自定义集合

时间:2008-12-18 10:39:43

标签: c# .net xml-serialization

我有一个继承自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>

有什么想法吗?越简单越好。感谢。

5 个答案:

答案 0 :(得分:13)

收藏品通常不会为额外的物业提供好地方。在序列化和数据绑定期间,如果项目看起来像集合(IListIEnumerable等,它们将被忽略 - 取决于场景)。

如果是我,我会封装收藏品 - 即。

[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(相当多的工作),但这仍然不适用于数据绑定等。基本上,这不是预期的用法。

答案 1 :(得分: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>

答案 2 :(得分:1)

正如尼尔·惠特克(Neil Whitaker)建议的那样,如果他的链接死了......

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

[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");
    }
}

答案 3 :(得分:0)

我一直在与Romaroo同样的问题进行斗争(想要在实现ICollection的类的xml序列化中添加属性)。我没有找到任何方法来公开集合类中的属性。我甚至尝试使用XmlAttribute标记并使我的属性显示为根节点的属性,但也没有运气。然而,我能够在我的类上使用XmlRoot标记从“ArrayOf ...”重命名它。以下是您感兴趣的一些参考资料:

答案 4 :(得分:0)

有时你只想做你想做的事;该框架应该被诅咒。

我在这里发布了一个答案Property of a List<T> Not Deserialized

做了OP想要做的事情。