Какие типы поддерживаются автоматической сериализацией XNB XNA?
Я прочитал в блоге Шона Харвгрива запись об автоматической сериализации и статью MSDN с обзором конвейера контента, но не смог найти список поддерживаемых типов.
Цитирование MSDN:
Начиная с XNA Game Studio 3.1, сериализация пользовательских данных в формате.XNB выполняется автоматически для простых типов, у которых нет существующего средства записи типов содержимого.
У меня не было проблем с этим, пока я не попытался использовать Queue
от System.Collections.Generic
который, я думаю, не поддерживается автоматической сериализацией.
Итак, есть ли список типов, поддерживаемых этим? И если это не поддерживается, мне нужно будет написать свой собственный ContentTypeWriter
а также ContentTypeReader
?
1 ответ
Предоставить полный список совместимых типов сложно, потому что сериализатор пытается быть совместимым с пользовательскими типами, которых он никогда раньше не видел. Поэтому любой список совместимых классов не может быть исчерпывающим. Как говорится в блоге Шона:
По умолчанию он сериализует все открытые поля и свойства вашего типа (при условии, что они не только для чтения).
Но давайте поговорим о коллекционных классах. По вышеприведенному правилу классы коллекций не будут правильно сериализованы (при использовании отражения), поскольку их коллекция объектов не является публичным свойством (также индексаторы не поддерживаются).
Интересно отметить, почему автоматическая сериализация такой коллекции не является встроенной функцией. Коллекция обычно реализует 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 И вам нужно поместить их в правильные сборки, чтобы у вас не возникало проблем с зависимостями.