2
votes

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?

1

1 Answers

5
votes

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:

  • Arrays
  • 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.