提供兼容类型的完整列表很棘手 - 因为序列化程序试图与它以前从未见过的自定义类型兼容。因此,任何兼容类的列表都不能详尽无遗。正如肖恩的博客文章所说:
默认情况下,它将序列化您类型的所有公共字段和属性(假设它们不是只读的)。
但是让我们谈谈集合类。根据上述规则,集合类将无法正确序列化(使用反射时),因为它们的对象集合不是公共属性(也不支持索引器)。
有趣的是,为什么像这样自动序列化集合不是内置功能。一个集合通常实现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);
}
}
请注意,我在GetRuntimeReader
此处的实现不处理targetPlatform
不是 Windows 的情况。而且您需要将它们放在正确的程序集中,这样您就不会遇到依赖性问题。