views:

293

answers:

2

Is it possible to Deserialize the following piece of XML into a Dictionary<int,string> object?

XML:

<Config>

<DatabaseConnections>
     <Connection Name="Source Connection" Value="ConnectionStringValue" />
     <Connection Name="Target Connection" Value="ConnectionStringValue" />
<DatabaseConnections>

<Config>

I have a class which will have a property of Dictionary<int,string> {get;set;}

I would like to use the following C# code to do this:

XmlSerializer xs = new XmlSerializer(typeof(Config));

using(StringReader sr = new StringReader(rootnode.OuterXml))
{
      return (Config)xs.Deserialize(sr);
}

Are there any alternatives to doing this?

A: 

You can use this class: SerializableDictionary.

You will need to change the property type, of course:

public class Config
{
     public SerializableDictionary<String, String> DatabaseConnections
     { get; set; }
}
Groo
+1  A: 

You cannot use the default XmlSerializer implementation to (de)serialize IDictionary objects to Xml. From the MSDN XmlSerializer documentation:

The XmlSerializer gives special treatment to classes that implement IEnumerable or ICollection. A class that implements IEnumerable must implement a public Add method that takes a single parameter. The Add method's parameter must be of the same type as is returned from the Current property on the value returned from GetEnumerator, or one of that type's bases.

The Dictionary<> class implements both interfaces, but does not have an Add method that takes a single parameter, so it fails.

More to the point, the xml serialization code explicitly disallows classes that implement IDictionary (from Reflector, looking at TypeScope.GetDefaultIndexer):

 if (typeof(IDictionary).IsAssignableFrom(type)) {
        if (memberInfo == null) {
            throw new NotSupportedException(...);
        }
        throw new NotSupportedException(...);
 }

So you can't even make the work by subclassing Dictionary<> and adding the required Add overload.

The article Generic Dictionaries vs. the XmlSerializer describes one workaround:

  1. First, decorate the Dictionary property with an XmlIgnore attribute. This tells the XmlSerializer to ignore that property, eliminating the reflection error.
  2. Create a new public property that takes and returns an array of DictionaryEntry objects. I tend to name these specially (_x_DictionaryName) so that it is clear one should not generally use this property.
  3. Serialize away.
Jeff Sternal