Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing Dictionary<string, object> when dictionary was initialized with case insensitive string comparer

I am serializing a Dictionary to XML. When I create a new dictionary I use the constructor to provide EqualityComparer without casing for instance

var tabs = new Dictionary<string,Tab>(StringComparer.OrdinalIgnoreCase);

I then serialize to XML and when I deserialize information about casing is lost - the deserialization is made to the Dictionary with GenericEqualityComparer, which apparently is case sensitive, because it doesn't find my keys if they are not cased correctly.

Any ideas how can I change it?

One way would be to create a new dictionary and copy the data from the deserialized over to the new one but this seems troublesome.

UPDATE:

The deserialization worked the whole time it is just that it deserializes the serialized Dictionary to one that does not use case insensitive keys.

like image 811
mare Avatar asked Aug 09 '10 13:08

mare


4 Answers

I know this question is quite old, but I recently found myself searching for how to do this.

Using .Net4 (like @mare said), you can create some really nice extension methods to make this a breeze. Check out https://stackoverflow.com/a/5941122/435460 for a nice and simple implementation.

After a lot of digging, this worked like a charm for me.

like image 62
JesseBuesking Avatar answered Nov 13 '22 11:11

JesseBuesking


Edit:

Per the comments, it appears this approach may be outdated in .NET 4.

End Edit

Dictionaries happen to require a little help to serialize and deserialize.

Here is a good example of an XML Serializable dictionary:

http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx

You can make it case insensitive by changing the class declaration and adding a constructor, and tweaking a line.

** EDIT: Corrected syntax error below. /EDIT**

public class SerializableDictionary<TValue>
    : Dictionary<string, TValue>, IXmlSerializable
{
    public SerializableDictionary()
        : base(StringComparer.InvariantCultureIgnoreCase)
    {
    }

    // ...
}

Change the line this.Add(key, value); to this[key] = value;.

At any rate, you may need to massage some of the details, but this should get you well on the road.

like image 3
kbrimington Avatar answered Nov 13 '22 11:11

kbrimington


You just have to wrap up your new dictionary in the Constructor:

Dictionary<string, Tab> tabs ;
tabs = new Dictionary<string, Tab>((Dictionary<string, Tab>)serializer.ReadObject(reader),StringComparer.OrdinalIgnoreCase);
like image 1
victoro Avatar answered Nov 13 '22 11:11

victoro


An old question I realize, but was just digging through the source to Dictionary and noticed that it should in fact serialize the Comparer:

info.AddValue(ComparerName, comparer, typeof(IEqualityComparer<tkey>));

Then in the implementation of IDeserializationCallback.OnDeserialization it retrieves the Comparar:

comparer = (IEqualityComparer<tkey>)m_siInfo.GetValue(ComparerName, typeof(IEqualityComparer<tkey>));

Classes implementing the interface IDeserializationCallback specify a method that should be executed after the an instance has been deserialized, but before its returned to your code.

Ref: Dictionary.cs GetObjectData and OnDeserialization methods

like image 1
Joey Ciechanowicz Avatar answered Nov 13 '22 11:11

Joey Ciechanowicz