Introduction
Contents
This is a class built on the articles of Shawn Hargreaves for using the IntermediateSerializer class to serialize collections of shared resources. In his article he only does the List<T> collection, but I had the need to serialize a Dictionary<T,K> instead, and maybe someone else will need it at some point, so here it is.
Background
The class is to be used with the IntermediateSerializer. It’s a class for serializing data to XML in XNA, and though it only works on the windows platform, it’s easier to use and has a lot more flexibility than the XmlSerializer. Introduction to the IntermediateSerializer can be found here, and a more extensive explanation can be found here. Following that, you might want to check out how to write your own ContentTypeSerializer, and specifically, how to do it for a collection of shared resources.
Code
As you have seen in the example about collections of shared resources, Shawn only deals with the List class, leaving us to work through the rest. Well, here is a Dictionary class with the values as shared resources.
Dictionary evolves to… SharedResourceDictionary!
The shared resource dictionary is nothing more than an empty wrapper:
- class SharedResourceDictionary<K, T> :
- Dictionary<K, T>
- { }
SharedResourceDictionarySerializer
This is where the serializing gets done. As a side note, you don’t need to do anything special to get the SharedResourceDictionary to use the SharedResourceDictionarySerializer, just by having both classes in your project it’s fine.
- [ContentTypeSerializer]
- class SharedResourceDictionarySerializer<T, K> :
- ContentTypeSerializer
- <SharedResourceDictionary<T, K>>
- {
- static ContentSerializerAttribute itemFormat =
- new ContentSerializerAttribute()
- {
- ElementName = "Item"
- };
- static ContentSerializerAttribute keyFormat =
- new ContentSerializerAttribute()
- {
- ElementName = "Key"
- };
- static ContentSerializerAttribute valueFormat =
- new ContentSerializerAttribute()
- {
- ElementName = "Value"
- };
- protected override void Serialize(
- IntermediateWriter output,
- SharedResourceDictionary<T, K> value,
- ContentSerializerAttribute format)
- {
- foreach (KeyValuePair<T, K> item in value)
- {
- output.Xml.WriteStartElement(
- itemFormat.ElementName);
- output.WriteObject(
- item.Key,
- keyFormat);
- output.WriteSharedResource(
- item.Value,
- valueFormat);
- output.Xml.WriteEndElement();
- }
- }
- protected override SharedResourceDictionary<T, K>
- Deserialize(
- IntermediateReader input,
- ContentSerializerAttribute format,
- SharedResourceDictionary<T, K> existingInstance)
- {
- if (existingInstance == null)
- {
- existingInstance =
- new SharedResourceDictionary<T, K>();
- }
- while (input.MoveToElement(itemFormat.ElementName))
- {
- T key;
- input.Xml.ReadToDescendant(
- keyFormat.ElementName);
- key = input.ReadObject<T>(keyFormat);
- input.Xml.ReadToNextSibling(
- valueFormat.ElementName);
- input.ReadSharedResource<K>(
- valueFormat,
- (K value) =>
- {
- existingInstance.Add(key, value);
- });
- input.Xml.ReadEndElement();
- }
- return existingInstance;
- }
- }
Sorry about the “strung out” format of the code, otherwise the blog settings compact it into an unreadable mess.
Calling the serializer
To use this code, we have a dictionary we want to serialize:
- SharedResourceDictionary<int, string> dictTest =
- new SharedResourceDictionary<int, string>();
To serialize it to Xml we do this:
- XmlWriterSettings settings = new XmlWriterSettings();
- settings.Indent = true;
- using (XmlWriter writer =
- XmlWriter.Create("out.xml", settings))
- {
- IntermediateSerializer.Serialize(
- writer,
- dictTest,
- null);
- }
To deserialize from Xml we do this:
- XmlReaderSettings settings = new XmlReaderSettings();
- using (XmlReader reader =
- XmlReader.Create("out.xml", settings))
- {
- this.dictTest = IntermediateSerializer.
- Deserialize<SharedResourceDictionary<int,string>>
- (reader, null);
- }
Notes
Special thanks to r2d2rigo for helping me hunt down some bugs in the code.
Hey man,
ReplyDeleteI know it's been like 2 years since you wrote that but I just got to this problem and your post helped me hunt down my own bugs in my implementation!
Thanks! :)