我已经阅读了Shawn Harvgreave关于自动序列化的博客文章和关于内容管道概述的MSDN文章,但我找不到支持的类型列表。
引用MSDN:
从XNA Game Studio 3.1开始,将自定义数据序列化为 .XNB格式是针对没有的简单类型自动完成的 有一个现有的内容类型编写者。
我尝试使用Queue
System.Collections.Generic
之前没有遇到任何问题,而我猜测自动序列化不支持ContentTypeWriter
。
那么,是否有支持的类型列表?如果不支持,我是否需要编写自己的ContentTypeReader
和{{1}}?
答案 0 :(得分:5)
提供完整的兼容类型列表很棘手 - 因为序列化程序试图与之前从未见过的自定义类型兼容。因此,任何兼容类列表都不能详尽无遗。正如Shawn's blog post所说:
默认情况下,它会序列化您的类型的所有公共字段和属性(假设它们不是只读的)。
但是,让我们谈谈收集课程。根据上述规则,集合类不能正确序列化(使用反射时),因为它们的对象集合不是公共属性(也不支持索引器)。
有趣的是指出为什么自动序列化这样的集合并不是一个内置功能。集合通常实现IEnumerable<T>
(如Queue<T>
所做),可以序列化。但这是只读的。 集合没有像IEnumerable
这样的标准界面。所以没有办法自动反序列化它们!
幸运的是, XNA为以下通用集合类型提供自定义读者/编写者:
List<T>
Dictionary<TKey, TValue>
序列化程序在可用时自动使用自定义读取器/写入器。因此,如果您希望它处理集合类(如Queue<T>
),那么您必须为它创建自己的ContentTypeWriter
和ContentTypeReader
。幸运的是,这并不太难 - 请参阅下面的未经测试的实现。
有关内置类型的完整列表,请参阅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的情况。而且你需要将它们放在正确的程序集中,这样你就不会遇到依赖问题。