Click here to Skip to main content
15,910,083 members
Articles / Programming Languages / C#
Technical Blog

Losing the Comparer when (De-)Serializing a Dictionary with the DataContractSerializer

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
22 Mar 2013CPOL1 min read 8.6K   1   1
Shows how to restore the Comparer when deserializing a dictionary with the DataContractSerializer.

I came across an interesting bug when working with a dictionary. I had a class using a dictionary as internal storage which should always ignore the casing of key when access the dictionary, Similar to the following code:

C#
[Serializable]
public class TestContainer
{
    private readonly string id;
    private readonly Dictionary<string, string> dictionary;
 
    public TestContainer(string id)
    {
        this.id = id;
        this.dictionary = 
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
    }
 
    public string GetValue(string key)
    {
        return this.dictionary[key];
    }
         
    public void AddValue(string key, string value)
    {
        this.dictionary.Add(key, value);
    }
}

There were unit tests checking all possible scenarios to make sure the values were always retrieved correctly (at least I thought so). The container was serialized and saved to a database by one application and deserialized by another application. The following sample has the same effect:

C#
DataContractSerializer serializer =  new DataContractSerializer(typeof(TestContainer));
using (MemoryStream memoryStream = new MemoryStream())
{
    serializer.WriteObject(memoryStream, testcontainer);
    memoryStream.Position = 0;
 
    deserializedTestContainer = (TestContainer)serializer.ReadObject(memoryStream);
}

Everything seemed to work just fine, until I encountered a bug where a value in the dictionary couldn't be found. I looked at the serialized xml (which was quite a pain being several MB big) and debugged to find the missing value. When I found the value in the dictionary I was really surprised and couldn't explain it. Then I realized the casing of the key wasn't consistent and began to wonder whether I had missed a scenario in my unit tests. But everything seemed to be covered and all tests passed. While inspecting the dictionary object I discovered that the dictionary's comparer was a GenericEqualityComparer. That means the (de-)serialization ignores the comparer of a dictionary and resets it to the default. To fix the issue, the [OnDeserialized] attribute can be used:

C#
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
    this.dictionary = new Dictionary<string, string>(
        this.dictionary, StringComparer.OrdinalIgnoreCase);
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
SuggestionDefault constrctor Pin
ZeBobo522-Mar-13 3:33
ZeBobo522-Mar-13 3:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.