DataMember Doesn't Work With CollectionDataContract

Confession time. One of my apps has a bug. When it tombstones, the app state is lost. So I was working away on getting my class to serialize into IsolatedStorage properly.

One of my classes was an extension to a Collection. In a somewhat lazy fashion I inherited from a System.Collection.Generic.List and added a few methods and properties inside the class. To make the collection serializable I added the CollectionDataContract attribute to the class. I also attributed the 'extra' members with DataMember attributes in order to get them to serialize as well. Parts of the class contained below.

 namespace DevFish
{
    [CollectionDataContract(ItemName = "Bucket", Namespace = "https://www.devfish.net")]
    public class Bucket : System.Collections.Generic.List<int>
    {
        [[DataMember()]
        public int MinElement { get; set; }  
  
        [[DataMember()]
        public int MaxElement { get; set; }

        [[DataMember()]
        public bool DoFullCheck = true;
        .... remainder of class removed for sake of brevity
    }   
} 

So happily I got running my programs and get very unhappy results. Upon inspecting the file content in isolated storage I note while the List content is there, the DataMember attrib'd properties didn't show up in the serialization. File contents below...

 <Randomizer xmlns:i="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://www.devfish.net">
<Bucket><Bucket>2</Bucket><Bucket>4</Bucket><Bucket>5</Bucket></Bucket>
<MaxValue>9</MaxValue><MinValue>1</MinValue></Randomizer>

Turns out, properties attrib'd DataMember inside a CollectionDataContract ( unlike regular DataContract ) do not serialize. So what to do? My approach. Wrap the collection class in a non-collection class, then attrib the collection as a DataMember . The main headache was surfacing out some methods like IndexOf and Add that I was using.

 [DataContract(Name = "Bucket", Namespace = "https://www.devfish.net")]
public class Bucket2
{
    [DataMember( Name="List")]
    public System.Collections.Generic.List<int> List { get; set; }

    public int MaxNumberOfElements
    {
        get { return MaxElement - MinElement; }
    }
        
    [DataMember()]
    public int MinElement { get; set; }  
  
    [DataMember()]
    public int MaxElement { get; set; }

    [DataMember()]
    public bool DoFullCheck = true;

    public void Add(int val)
    {
        this.List.Add(val);
    }
        

    public int IndexOf(int val)
    {
        return this.List.IndexOf(val);
    }

The class serialized fine after that as you can see below. The list gets kinda verbose, but we'll see how it plays out. BinarySerializer may be the next trick. This blog post dedicated to SEO and saving someone the two or so hours it cost me to wrestle this out.

 <Randomizer xmlns:i="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://www.devfish.net">
<Bucket>
<DoFullCheck>true</DoFullCheck>
<List xmlns:d3p1="https://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d3p1:int>3</d3p1:int><d3p1:int>1</d3p1:int></List>
<MaxElement>9</MaxElement>
<MinElement>1</MinElement>
</Bucket><MaxValue>9</MaxValue><MinValue>1</MinValue>
</Randomizer>

Comments