开发者

Control serialization of derived type

Given a type such as:

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

How can I get the SomeMessage property to be serialized along with the collection without overriding serialization itself?

What I am getting is:

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

and what I want is:

<FooList>
    <SomeMessage />
    <Foo />
    <Foo />
    &l开发者_如何学编程t;Foo />
</FooList>

For whatever reason, (I think it is because the serialization being used for the generic list doesn't see the new property) it isn't being written out.

In case it matters, here is what I am using to serialize it.

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


When the XmlSerializer serializes a collection, it only takes the items of the collection into account. Any extra property declared in the class is ignored. You will either have to implement IXmlSerializable to provide your own serialization logic, or change the design of your class.

You could do something like that:

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

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


If you need to implement the XmlChoiceIdentifierAttribute, the XmlSerializer will be able to handle your requirements properly.

More info on the topic here:

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

Sample code:

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

If you prefer to generate the serializable class via xsd.exe, then the xsd schema should look something like this (notice the xs:choice tag):

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


When deriving from a collection class the XmlSeralizier will only serialize the elements in the collection. One way to work around this is to create a class that wraps the collection and SomeMessage and have that serialized.

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

Then you could to this:

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

A detailed discussion is available here.


Try decorating SomeMessage with an [XMLElement] attribute, to force the XMLSerializer to include it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜