XNA的自动XNB序列化支持哪些类型?

Jus*_*les 2 c# xna serialization content-pipeline

我已经阅读了Shawn Harvgreave关于自动序列化的博客文章和关于内容管道概述的MSDN文章,但我找不到支持的类型列表.

引用MSDN:

从XNA Game Studio 3.1开始,对于没有现有内容类型编写器的简单类型,自动完成自定义数据到.XNB格式的序列化.

直到我试图用我还没有这个问题,QueueSystem.Collections.Generic我猜是不是由自动序列化的支持.

那么,是否有一个支持的类型列表?而如果不支持的话,会我需要写我自己的ContentTypeWriterContentTypeReader

And*_*ell 5

提供完整的兼容类型列表很棘手 - 因为序列化程序试图与之前从未见过的自定义类型兼容.因此,任何兼容类列表都不能详尽无遗.正如Shawn的博客文章所说:

默认情况下,它将序列化您的类型的所有公共字段和属性(假设它们不是只读的).

但是我们来谈谈集合类.根据上述规则,集合类将无法正确序列化(使用反射时),因为它们的对象集合不是公共属性(也不支持索引器).

有趣的是指出为什么自动序列化这样的集合不是内置功能.一个集合通常实现IEnumerable<T>(像是Queue<T>),可以序列化.但这是只读的.有没有像标准接口,IEnumerable用于编写到集合.所以没有办法自动反序列化它们!

幸运的是,XNA为以下通用集合类型提供了自定义读取器/写入器:

  • 数组
  • List<T>
  • Dictionary<TKey, TValue>

序列化程序在可用时自动使用自定义读取器/写入器.所以,如果你希望它处理的集合类(像Queue<T>),那么你必须创建自己的ContentTypeWriter,并ContentTypeReader为它.幸运的是,这并不太难 - 请参阅下面的未经测试的实现.

有关内置类型的完整列表,请参阅XNB格式规范.同样,这仅涵盖了内置类型.可以通过反射或通过提供自定义读取器/写入器对来支持其他类型.


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);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我在GetRuntimeReader这里的实现不处理targetPlatform不是Windows的情况.而且你需要将它们放在正确的程序集中,这样你就不会遇到依赖性问题.