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

时间:2012-10-18 22:45:20

标签: c# serialization xna content-pipeline

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

引用MSDN:

  

从XNA Game Studio 3.1开始,将自定义数据序列化为   .XNB格式是针对没有的简单类型自动完成的   有一个现有的内容类型编写者。

我尝试使用Queue System.Collections.Generic之前没有遇到任何问题,而我猜测自动序列化不支持ContentTypeWriter

那么,是否有支持的类型列表?如果不支持,我是否需要编写自己的ContentTypeReader和{{1}}?

1 个答案:

答案 0 :(得分:5)

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

  

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

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

有趣的是指出为什么自动序列化这样的集合并不是一个内置功能。集合通常实现IEnumerable<T>(如Queue<T>所做),可以序列化。但这是只读的。 集合没有像IEnumerable这样的标准界面。所以没有办法自动反序列化它们!

幸运的是, XNA为以下通用集合类型提供自定义读者/编写者

  • 阵列
  • List<T>
  • Dictionary<TKey, TValue>

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

有关内置类型的完整列表,请参阅XNB Format规范。这又涵盖了内置类型。其他类型可以通过反射或提供自定义读/写对来支持。


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);
    }
}

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