This is my class structure:
class DataItem
{
public string Id { get; set; }
public string Type { get; set; }
private Dictionary
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);
}
}
}
I know this has been answered before, but since I have a very concise way (code) for doing IDictionary serialization with the DataContractSerializer class (used by WCF, but could and should be used anywhere) I couldn't resist contributing it here:
public static class SerializationExtensions
{
public static string Serialize<T>(this T obj)
{
var serializer = new DataContractSerializer(obj.GetType());
using (var writer = new StringWriter())
using (var stm = new XmlTextWriter(writer))
{
serializer.WriteObject(stm, obj);
return writer.ToString();
}
}
public static T Deserialize<T>(this string serialized)
{
var serializer = new DataContractSerializer(typeof(T));
using (var reader = new StringReader(serialized))
using (var stm = new XmlTextReader(reader))
{
return (T)serializer.ReadObject(stm);
}
}
}
This works perfectly in .NET 4 and should also work in .NET 3.5, although I didn't test it yet. I did the streaming to string because it was more convenient to me, although I could have introduced a lower-level serialization to Stream and then used it to serialize to strings, but I tend to generalize only when needed (just like premature optimization is evil, so it is premature generalization...)
Usage is very simple:
// dictionary to serialize to string
Dictionary<string, object> myDict = new Dictionary<string, object>();
// add items to the dictionary...
myDict.Add(...);
// serialization is straight-forward
string serialized = myDict.Serialize();
...
// deserialization is just as simple
Dictionary<string, object> myDictCopy =
serialized.Deserialize<Dictionary<string,object>>();
myDictCopy will be a verbatim copy of myDict.
You'll also notice that the generic methods provided will be able to serialize any type (to the best of my knowledge) since it is not limited to IDictionary interfaces, it can be really any generic type T.
Hope it helps someone out there!
You can't but another way to do this would be to create an simple object which hold Value and Key properties. Then use List(Of thatObject) and it should work. But that depend if you only want to transport a value key data cause all others methods which is part of dictionary won't be available.
I suggest you use the DataContractSerializer. It does support dictionaries.
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.