20

I'm having a situation here, I need my class to be inherited from List<ItemType>, but when I do this XmlSerializer does not serialize any property or field declared in my class, the following sample demonstrates:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        DoSerialize();
    }
    private void DoSerialize()
    {
        MyClass obj = new MyClass();
        obj.Add(1);
        obj.Add(2);
        obj.Add(3);
        XmlSerializer s = new XmlSerializer(typeof(MyClass));
        StringWriter sw = new StringWriter();
        s.Serialize(sw, obj);
    }
}
[Serializable]
[XmlRoot]
public class MyClass : List<int>
{
    public MyClass()
    {
    }
    int myAttribute = 2011;
    [XmlAttribute]
    public int MyAttribute
    {
        get
        {
            return myAttribute;
        }
        set
        {
            myAttribute = value;
        }
    }
}

the resulting XML:

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <int>1</int>
  <int>2</int>
  <int>3</int>
</ArrayOfInt>
John Saunders
  • 157,405
  • 24
  • 229
  • 388
Esam Bustaty
  • 296
  • 4
  • 12
  • 1
    This is one of many reasons you generally shouldn't subclass `List`. – Kirk Woll Feb 21 '11 at 17:29
  • @kirk: Yeah, I think also the same, but this time I have to, I didn't start the project, it's like this and I have to do serialization on it – Esam Bustaty Feb 21 '11 at 17:36
  • @Kirk not disagreeing with that principle, but here (per the link in @driis answer) the problem is actually that implementing `IEnumerable` *at all* means your own properties don't get serialised! Which seems pretty harsh... – AakashM Feb 21 '11 at 17:45
  • possible duplicate of [XmlSerializer doesn't serialize everything in my class](http://stackoverflow.com/questions/1797947/xmlserializer-doesnt-serialize-everything-in-my-class) – AakashM Feb 21 '11 at 17:46
  • @AakashM Sorry for the duplicate, I searched but didn't find it, perhaps I was using the wrong kewords – Esam Bustaty Feb 21 '11 at 17:56
  • @AakashM -- it's bitten me too in the past. But really, what business do entities have implementing `IEnumerable` *or* `IList`? – Kirk Woll Feb 21 '11 at 18:07
  • Also, for posterity, `[Serializable]` is ignored by the XML Serializer. – John Saunders Feb 21 '11 at 19:01

2 Answers2

25

This is by design. I don't know why this decision was made, but it is stated in the documentation:

  • Classes that implement ICollection or IEnumerable. Only collections are serialized, not public properties.

(Look under "Items that can be serialized" section). Someone has filed a bug against this, but it won't be changed - here, Microsoft also confirms that not including the properties for classes implementing ICollection is in fact the behaviour of XmlSerializer.

A workaround would be to either:

  • Implement IXmlSerializable and control serialization yourself.

or

  • Change MyClass so it has a public property of type List (and don't subclass it).

or

  • Use DataContractSerializer, which handles this scenario.
driis
  • 151,614
  • 43
  • 262
  • 332
  • I thought that would be the answer but I was just wanted to make sure, I asked cuz I couldn't find it in the documentation, Thank you – Esam Bustaty Feb 21 '11 at 17:54
  • Hi, found this question here like 5 years later. Since this is still a problem - how would you do that with DataContractSerializer? – greece57 Jul 26 '16 at 17:24
  • Have you tried to solve it with `DataContractSerializer`. Can't get it working (https://stackoverflow.com/questions/55301839/serializing-class-inherited-from-list-using-datacontractserializer-does-not-se) – marsh-wiggle Mar 22 '19 at 15:22
5

Here's a though for you to consider.

You can have a class that is a container class like this:

class ContainerObject
{
     public int MyNewProperty { get; set; }

     [XmlElement("")]
     public List<int> MyList { get; set; }
}

The trick is to have XmlElement name = "" above the List element.

When this is serialized into xml, you will have:

<ContainerObject>
   <MyNewProperty>...</MyNewProperty>

   <int>...</int>
   <int>...</int>

</ContainerObject>

If you like, you can also create another class for items in a list

 class MyItem
 {
     public int MyProperty {get;set;} 

 } 

and then instead of having List of ints, have a List of MyItems.

This was you control XmlElement name of every item in a list.

I hope this was helpful.

dexter.ba
  • 274
  • 2
  • 5