Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# inheriting generic collection and serialization

The setup:

class Item
{
    private int _value;

    public Item()
    {
        _value = 0;
    }

    public int Value { get { return _value; } set { _value = value; } }
}

class ItemCollection : Collection<Item>
{
    private string _name;

    public ItemCollection()
    {
        _name = string.Empty;
    }

    public string Name { get {return _name;} set {_name = value;} }
}

Now, trying to serialize using the following code fragment:

ItemCollection items = new ItemCollection();

...

XmlSerializer serializer = new XmlSerializer(typeof(ItemCollection));
using (FileStream f = File.Create(fileName))
    serializer.Serialize(f, items);

Upon looking at the resulting XML I see that the ItemCollection.Name value is not there!

I think what may be happening is that the serializer sees the ItemCollection type as a simple Collection thus ignoring any other added properties...

Is there anyone having encountered such a problem and found a solution?

Regards,

Stécy

like image 943
Stécy Avatar asked Mar 20 '09 13:03

Stécy


3 Answers

This behavior is "By Design". When deriving from a collection class the Xml Seralizier will only serialize the collection elements. To work around this you should create a class that encapsulates the collection and the name and have that serialized.

class Wrapper
{
    private Collection<Item> _items;
    private string _name;

    public Collection<Item> Items { get {return _items; } set { _items = value; } }
    public string Name { get { return _name; } set { _name = value; } }
}

A detailed discussion is available here: http://blogs.vertigo.com/personal/chris/Blog/archive/2008/02/01/xml-serializing-a-derived-collection.aspx

like image 188
JaredPar Avatar answered Oct 21 '22 10:10

JaredPar


XmlSerializer is evil. That said, any object that implements IEnumerable will be serialized as an simple collection, ignoring any extra properties you've added yourself.

You will need to create a new class that holds both your property and a property that returns the collection.

like image 26
sisve Avatar answered Oct 21 '22 09:10

sisve


I am not sure if I am missing something, but do you want the resulting xml to be

<ItemCollection>
   <Name>name val</Name>
   <Item>
      <Value>1</alue>
   </Item
   <Item>
      <Value>2</alue>
   </Item
</ItemCollection>

If so, just apply the XmlRoot attribute to the itemcollection class and set the element name...

[XmlRoot(ElementName="ItemCollection")]
public class ItemCollection : Collection<Item>
{
   [XmlElement(ElementName="Name")]
   public string Name {get;set;}
}

This will instruct the serializer to output the required name for you collection container.

like image 32
NoelAdy Avatar answered Oct 21 '22 10:10

NoelAdy