我有一个如下所示的游戏数据类:
public class SaveGameData {
public virtual List<PropertyContainer> properties {get; set; }
}
这些课程也是如此:
public class PropertyContainer {
public Property property {get; set; }//Could be set to DerivedProperty
}
public class Property {
public int BasePropertyData {get; set;}
}
public class DerivedProperty : Property {
public int DerivedPropertyData {get; set; }
}
我正在尝试在播放会话之间保存/加载此数据,我正在使用XML序列化/反序列化来完成此过程。
问题在于,在PropertyContainer类中,派生属性有时用于子类的属性类,如下所示:
PropertyContainer container = new PropertyContainer();
container.property = derivedProperty;
当容器被序列化时,派生类及其特殊属性也会保存,这里没问题。
这是序列化代码:
serializer = new System.Xml.Serialization.XmlSerializer(typeof(SaveGameData));
SaveGameData dataToSave = GetSaveGameData();
using (var stream = new StringWriter()) {
serializer.Serialize(stream, dataToSave);
...write to file...
}
序列化过程似乎正在起作用,因为派生类被识别并正确保存到XML文件中,XML输出如下所示:
<?xml version="1.0" encoding="utf-16"?>
<SaveGameData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<properties>
<PropertyContainer>
<property xsi:type="DerivedProperty">
<BasePropertyData>1</BasePropertyData>
<DerivedPropertyData>1</DerivedPropertyData>
</property>
</PropertyContainer>
</properties>
</SaveGameData>
但是当反序列化XML文件时,所有派生类都将被丢弃。这是反序列化代码:
SaveGameData result;
string data = ReadSaveGameData();
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SaveGameData));
using (StringReader stream = new StringReader(savedGame)) {
result = (SaveGameData)serializer.Deserialize(stream);
}
这意味着在加载XML数据之后,在派生属性上调用GetType()
(例如。saveGameData.properties[0].GetType()
,假设属性为DerivedProperty)将产生基类,即Property
;通过扩展,它会丢弃所有DerivedProperty的属性。有问题。
P.S:
我尝试添加XmlInclude
属性,但没有改变:
[System.Xml.Serialization.XmlInclude(typeof(DerivedProperty))]
public class Property {
...
}
我该如何解决这个问题?我的方法有可行的替代方案吗?
答案 0 :(得分:0)
一种选择是切换到DataContractSerializer
。然后使用KnownTypeAttribute
标识子类。
public class PropertyContainer {
public Property property {get; set; }//Could be set to DerivedProperty
}
[KnownType(typeof(DerivedProperty))]
public class Property {
public int BasePropertyData {get; set;}
}
public class DerivedProperty : Property {
public int DerivedPropertyData {get; set; }
}
答案 1 :(得分:0)
使用Property
装饰[XmlInclude(typeof(DerivedProperty))]
课程应该有效。事实上,如果没有它,XmlSerializer
甚至不会让你首先序列化DerivedProperty
!
以下程序是基于您的代码的工作示例。请确认您的计算机上的控制台输出是True
。如果是,您需要确定代码与原始尝试的不同之处。然后更新您的问题,以便我们深入挖掘。
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
class Program
{
static void Main()
{
string savedGame = @"
<SaveGameData xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<properties>
<PropertyContainer>
<property xsi:type='DerivedProperty'>
<BasePropertyData>1</BasePropertyData>
<DerivedPropertyData>1</DerivedPropertyData>
</property>
</PropertyContainer>
</properties>
</SaveGameData>";
XmlSerializer serializer = new XmlSerializer(typeof(SaveGameData));
SaveGameData result;
using (StringReader stream = new StringReader(savedGame))
{
result = (SaveGameData)serializer.Deserialize(stream);
}
Console.WriteLine(result.properties[0].property is DerivedProperty); // True
}
}
public class SaveGameData
{
public virtual List<PropertyContainer> properties { get; set; }
}
public class PropertyContainer
{
public Property property { get; set; }//Could be set to DerivedProperty
}
[XmlInclude(typeof(DerivedProperty))]
public class Property
{
public int BasePropertyData { get; set; }
}
public class DerivedProperty : Property
{
public int DerivedPropertyData { get; set; }
}