属性的派生类被丢弃(即:(用基类代替),用于XML反序列化

本文关键字:基类 反序列化 XML 用于 派生 属性 | 更新日期: 2023-09-27 18:04:41

我有一个游戏数据类,看起来像这样:

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类中,有时使用派生属性来替代property类,如下所示:
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。史:我尝试添加XmlInclude属性,但没有改变:

[System.Xml.Serialization.XmlInclude(typeof(DerivedProperty))]
public class Property {
...
}  

如何解决这个问题?有可行的替代方法吗?

属性的派生类被丢弃(即:(用基类代替),用于XML反序列化

[XmlInclude(typeof(DerivedProperty))]装饰Property类应该是有效的。实际上,如果没有它,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; }
}

一种选择是切换到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; }    
}