控制派生类型的序列化

时间:2010-09-27 20:39:14

标签: c# xml serialization

给出如下类型:

public class FooList : List<Foo>
{
    public string SomeMessage { get; set; }
}

如何在不重写序列化的情况下将SomeMessage属性与集合一起序列化?

我得到的是:

<FooList>
    <Foo />
    <Foo />
    <Foo />
</FooList>

我想要的是:

<FooList>
    <SomeMessage />
    <Foo />
    <Foo />
    <Foo />
</FooList>

无论出于何种原因,(我认为这是因为用于通用列表的序列化没有看到新属性)它没有被写出来。

如果重要,这就是我用它来序列化它。

FooList content = new FooList();
content.SomeMessage="this is a test";
//add foos

using (TextWriter writer = new StreamWriter("C:\\foos.xml"))
{
    XmlSerializer serializer = new XmlSerializer(typeof(FooList));
    serializer.Serialize(writer, content);
}

4 个答案:

答案 0 :(得分:2)

如果您需要实施XmlChoiceIdentifierAttribute,XmlSerializer将能够正确处理您的要求。

有关此主题的更多信息:

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlchoiceidentifierattribute.aspx

示例代码:

[System.Xml.Serialization.XmlElementAttribute("myType1", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("myType2", typeof(string))]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
public string[] Items 
{
    get 
    {
        return this.itemsField;
    }
    set 
    {
        this.itemsField = value;
    }
}

如果您希望通过xsd.exe生成可序列化类,则xsd架构应如下所示(请注意xs:choice标记):

<xs:complexType name="rowElement">
  <xs:sequence>
    <xs:choice maxOccurs="unbounded">
      <xs:element name="myType1" type="xs:string"/>
      <xs:element name="myType2" type="xs:string"/> 
    </xs:choice>
  </xs:sequence>
</xs:complexType>

... HTH

答案 1 :(得分:1)

XmlSerializer序列化集合时,它只会考虑集合中的项目。在类中声明的任何额外属性都将被忽略。您必须实现IXmlSerializable以提供自己的序列化逻辑,或者更改类的设计。

你可以这样做:

[XmlRoot("FooList")]
public class FooListContainer
{
    public string SomeMessage { get; set; }

    [XmlElement("Foo")]
    public List<Foo> Foos { get; set; }
}

答案 2 :(得分:1)

从集合类派生时,XmlSeralizier将仅序列化集合中的元素。解决此问题的一种方法是创建一个包装集合的类,SomeMessage并将其序列化。

  [XmlRoot("FooList")]
  public class CollectionWrapper
  {
     [XmlElement]
     public List<Foo> Items { get; set; }
     public string SomeMessage { get; set; }
  }

然后你可以这样:

     CollectionWrapper cw = new CollectionWrapper();
     cw.Items = new List<Foo>();
     cw.Items.Add(foo1);
     cw.Items.Add(foo2);
     cw.SomeMessage = "this is a test";

     using (TextWriter writer = new StreamWriter("C:\\foos.xml"))
     {
        XmlSerializer serializer = new XmlSerializer(typeof(CollectionWrapper));
        serializer.Serialize(writer, cw);
     }

可以进行详细讨论here

答案 3 :(得分:0)

尝试使用[XMLElement]属性装饰SomeMessage,以强制XMLSerializer包含它。