Search code examples
c#xml-serialization

Serializing class implementing ICollection


I have a collection class implementing ICollection<T> with a few custom attributes thrown in for completeness..

In this simplistic sample, its a simple Request/Results pattern with the request itself being passed back as an attribute of the results class.

[Serializable]
public class MyRequest
{
    public int SearchID { get; set; }
}

[Serializable]
public class MyResults : ICollection<MyElement>
{
    public MyRequest RequestDetails { get; set; }
    private ICollection<MyElement> _list = new List<MyElement>();

    /* ICollection interface methods removed */
}

[Serializable]
public class MyElement
{
    public int ID { get; set; }
}

Here's the sample program to instantiate and then output a serialized string.

class Program
{
    static void Main(string[] args)
    {
        MyResults m = new MyResults();
        m.RequestDetails = new MyRequest() { SearchID = 1 };

        for (int i = 1; i <= 5; i++)
        {
            m.Add(new MyElement { ID = i });
        }

        XmlDocument xmlDoc = new XmlDocument();
        XmlSerializer xmlSerializer = new XmlSerializer(m.GetType());
        using (MemoryStream xmlStream = new MemoryStream())
        {
            xmlSerializer.Serialize(xmlStream, m);
            xmlStream.Position = 0;
            xmlDoc.Load(xmlStream);
        }

        System.Diagnostics.Debug.WriteLine(xmlDoc.OuterXml);
    }
}

The problem is that the output is not including the MyRequest details...

<?xml version="1.0"?>
<ArrayOfMyElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <MyElement>
        <ID>1</ID>
    </MyElement>
    <MyElement>
        <ID>2</ID>
    </MyElement>
    <MyElement>
        <ID>3</ID>
    </MyElement>
    <MyElement>
        <ID>4</ID>
    </MyElement>
    <MyElement>
        <ID>5</ID>
    </MyElement>
</ArrayOfMyElement>

Solution

  • XmlSerializer always ignores extra properties when serializing a collection; the only way to do it, as far as I know, is not to implement ICollection<MyElement> on your MyResults class, and instead expose the collection as a property:

    public class MyResults
    {
        public MyRequest RequestDetails { get; set; }
        public ICollection<MyElement> Items { get; set; }
    }
    

    (the Serializable attribute isn't needed for XML serialization)