I've read Shawn Harvgreave's blog entry about automatic serialization and the MSDN article on an overview of the content pipeline, but I couldn't find a list of the types supported.
Quoting MSDN:
Starting with XNA Game Studio 3.1, the serialization of custom data to the .XNB format is done automatically for simple types that do not have an existing content type writer.
I haven't had problems with this until I tried to use a Queue
from System.Collections.Generic
which I'm guessing isn't supported by the automatic serialization.
So, is there a list of types supported by this? And if it isn't supported, will I need to write my own ContentTypeWriter
and ContentTypeReader
?
Providing a complete list of compatible types is tricky - because the serializer tries to be compatible with custom types it has never seen before. So any list of compatible classes cannot be exhaustive. As Shawn's blog post says:
By default it will serialize all the public fields and properties of your type (assuming they are not read-only).
But let's talk about collection classes. By the above rule, collection classes won't be serialized correctly (when using reflection), because their collection of objects is not a public property (also, indexers aren't supported).
It's interesting to point out why automatically serializing a collection like this isn't a built-in feature. A collection usually implements IEnumerable<T>
(like Queue<T>
does), which could be serialized. But that's read-only. There's no standard interface like IEnumerable
for writing to collections. So there's no way to automatically deserialize them!
Fortunately, XNA provides custom readers/writers for the following generic collection types:
List<T>
Dictionary<TKey, TValue>
The serializer automatically uses custom readers/writers when they are available. So if you want it to handle a collection class (like Queue<T>
), then you must create your own ContentTypeWriter
and ContentTypeReader
for it. Fortunately this isn't too hard - see below for an untested implementation.
For a full list of built-in types, see the XNB Format specification. Again this just covers the built-in types. Other types can be supported through reflection or by providing custom reader/writer pairs.
class QueueReader<T> : ContentTypeReader<Queue<T>>
{
public override bool CanDeserializeIntoExistingObject { get { return true; } }
protected override Queue<T> Read(ContentReader input, Queue<T> existingInstance)
{
int count = input.ReadInt32();
Queue<T> queue = existingInstance ?? new Queue<T>(count);
for(int i = 0; i < count; i++)
queue.Enqueue(input.ReadObject<T>());
return queue;
}
}
[ContentTypeWriter]
class QueueWriter<T> : ContentTypeWriter<Queue<T>>
{
public override string GetRuntimeReader(TargetPlatform targetPlatform)
{
return typeof(QueueReader<T>).AssemblyQualifiedName;
}
public override bool CanDeserializeIntoExistingObject { get { return true; } }
protected override void Write(ContentWriter output, Queue<T> value)
{
output.Write(value.Count);
foreach(var item in value)
output.WriteObject<T>(item);
}
}
Note that my implementation of GetRuntimeReader
here doesn't handle cases where targetPlatform
isn't Windows. And you'll need to put these in the right assemblies so you don't get dependency issues.