tags:

views:

48

answers:

4

This is my class structure:

class DataItem
{
   public string Id { get; set; }
   public string Type { get; set; }

   private Dictionary<string, DataProperty> properties = new Dictionary<string, DataProperty>();

   public Dictionary<string, DataProperty> Properties
   {
       get { return properties; }
       set { properties = value; }
   }
}

public class DataProperty
{    
      public string Key { get; set; }
      public string Value { get; set; }
      public bool Required { get; set; }
}

This is XML I want to use (NOTE: I can change the xml if needed):

<Data>
  <DataItem>
    <id>ph15</id>
    <type>core</type>
    <properties>
      <DataProperty>
        <key>size</key>
        <value>50%</value>
        <required>false</required>
      </DataProperty>
      <DataProperty>
        <key>color</key>
        <value>red</value>
        <required>true</required>
      </DataProperty>
    </properties>
  </DataItem>
  <DataItem>
    <id>ph234</id>
    <type>core</type>
    <properties>
    </properties>
  </DataItem>
</Data>

Eventually XML should be loaded into another dictionary:

private Dictionary<string, DataItem> Mydata;
A: 

What's wrong with using XmlSerializer?

John Weldon
XmlSerializer does not support dictionary types.
LBushkin
It doesn't support IDictionary<,>
Aren
Ah, yes. Makes sense.
John Weldon
+1  A: 

Unfortunately, generic dictionaries are not xml serializable.

The workaround is to greate a separate field specifically to support serialization that exposes the elements of the dictionary as a list of key/value pairs. You then also have to mark the dictionary member with the XmlIgnore attribute.

Alternatively, you can use something other than XmlSerializer (like DataContractSerializer) which does support dictionary types.

Here's a link to an article which provides a good example of how modify your type to support XML Serialization with a dictionary.

One important point if you use this code - the serialized items may appear in arbitrary order in the output. This is a consequence of using dictinoaries (which are unordered) as the storage model for your data.

[XmlIgnore()]   
public Dictionary<string, DataProperty> Properties
{   
    set { properties = value; }   
    get { return properties ; }   
}


[XmlArray("Stuff")]   
[XmlArrayItem("StuffLine", Type=typeof(DictionaryEntry))]   
public DictionaryEntry[] PropertiesList
{   
    get  
    {   
        //Make an array of DictionaryEntries to return   
        DictionaryEntry[] ret=new DictionaryEntry[Properties.Count];   
        int i=0;   
        DictionaryEntry de;   
        //Iterate through Stuff to load items into the array.   
        foreach (KeyValuePair<string, DataProperty> props in Properties)   
        {   
            de = new DictionaryEntry();   
            de.Key = props.Key;   
            de.Value = props.Value;   
            ret[i]=de;   
            i++;   
        }   
        return ret;   
    }   
    set  
    {   
        Properties.Clear();   
        for (int i=0; i<value.Length; i++)   
        {   
            Properties.Add((string)value[i].Key, (DataProperty)value[i].Value);   
        }   
    }   
}  
LBushkin
i liked the DataContract, and have another question: because DataItem class represent an item in Mydata dictionary, do I need to create another class to wrap it?
ilann
@ilann - No you shouldn't have to do that. Yo should be able to serialize `Mydata` directly so long as you provide the necessary metadata to define how members will be serialized (ie nodes, attributes, cdata, etc).
LBushkin
A: 

The short answer: You cant

This is because even though you can imagine the serialization scheme, .NET Serializer cannot guarantee that the keys re-serialized will have the same hash value.

Long answer: You can, but it's a lot of work

The solution for you is to either do manual serialization of the entire object, or to replace Dictionary with a simple Wrapper Property that wraps IDictionary, but exposes it as a list of pairs. (you can convert it later if you need it.)

However: this leaves the same problem as above, you cannot gaurantee a re-serialized key will have the same hashcode as before it was serialized.

Aren
A: 

I suggest you use the DataContractSerializer. It does support dictionaries.

John Saunders