【发布时间】:2011-11-28 01:03:12
【问题描述】:
我正在构建一个 XNA 游戏,我正在尝试完全保存游戏/地图等状态,然后能够从完全相同的状态加载和恢复。
我的游戏逻辑包含相当复杂的元素(用于序列化),例如引用、委托等。我已经进行了数小时的研究并决定最好使用保留对象引用的DataContractSerializer。 (我也解决了委托,但这是另一个主题)我没有问题序列化和反序列化状态,正确和完整地重新创建对象、字段、列表甚至对象引用。但是我遇到了循环引用的问题。考虑这种情况:
class X{
public X another;
}
//from code:
X first = new X();
X second = new X();
first.another = second;
second.another = first;
尝试序列化 X 将导致抱怨循环引用的异常。如果我注释掉最后一行,它工作正常。好吧,我可以想象为什么会这样,但我不知道如何解决它。我在某处读到我可以使用DataContract 属性并将IsReference 设置为true,但它对我没有任何改变——仍然出现错误。 (无论如何我都想避免它,因为我正在处理的代码是可移植代码,并且有一天也可能在 Xbox 上运行,而且 Xbox 的可移植库不支持 DataContract 所在的程序集。)
这是序列化的代码:
class DataContractContentWriterBase<T> where T : GameObject
{
internal void Write(Stream output, T objectToWrite, Type[] extraTypes = null)
{
if (extraTypes == null) { extraTypes = new Type[0]; }
DataContractSerializer serializer = new DataContractSerializer(typeof(T), extraTypes, int.MaxValue, false, true, null);
serializer.WriteObject(output, objectToWrite);
}
}
我正在从这个类中调用这段代码:
[ContentTypeWriter]
public class PlatformObjectTemplateWriter : ContentTypeWriter<TWrite>
(... lots of code ...)
DataContractContentWriterBase<TWrite> writer = new DataContractContentWriterBase<TWrite>();
protected override void Write(ContentWriter output, TWrite value)
{
writer.Write(output.BaseStream, value, GetExtraTypes());
}
对于反序列化:
class DataContractContentReaderBase<T> where T: GameObject
{
internal T Read(Stream input, Type[] extraTypes = null)
{
if (extraTypes == null) { extraTypes = new Type[0]; }
DataContractSerializer serializer = new DataContractSerializer(typeof(T), extraTypes, int.MaxValue, false, true, null);
T obj = serializer.ReadObject(input) as T;
//return obj.Clone() as T; //clone falan.. bi bak iste.
return obj;
}
}
它被调用:
public class PlatformObjectTemplateReader : ContentTypeReader<TRead>
(lots of code...)
DataContractContentReaderBase<TRead> reader = new DataContractContentReaderBase<TRead>();
protected override TRead Read(ContentReader input, TRead existingInstance)
{
return reader.Read(input.BaseStream, GetExtraTypes());
}
地点:
PlatformObjectTemplate 是我喜欢写的类型。
有什么建议吗?
解决方案:就在几分钟前,我意识到我没有用DataMember 属性标记字段,在我添加DataContract 属性之前,XNA 序列化程序是以某种方式充当“默认”序列化程序。现在,我已经标记了所有对象,现在一切正常。现在我的模型中有没有问题的循环引用。
【问题讨论】:
-
如果您正在寻找替代序列化程序,protobuf-net(至少它的 v2)可能满足您的要求。
-
谢谢,它看起来不错,但我需要一个可移植的类库兼容代码。
-
你检查了吗?不兼容吗?
-
在主页上,它指出,protobuf-net 是一个 .NET 实现,允许您高效轻松地序列化您的 .NET 对象。它与大多数 .NET 系列兼容,包括 .NET 2.0/3.0/3.5、.NET CF 2.0/3.5、Mono 2.x、Silverlight 2 等。 这些似乎不支持 PCL ,但是。
-
仅仅因为它没有列出 PCL 并不意味着它不会工作。 PCL 本身旨在与那些非常相同的(Microsoft)框架兼容。因此,如果无法针对 PCL 成功构建 protobuf-net,我会感到惊讶。
标签: c# .net-4.0 xna portability datacontractserializer