通过仅在基类中定义serialize方法来序列化具有继承的对象?

时间:2013-12-25 17:07:53

标签: c# serialization binaryformatter

我目前正在用C#进行游戏(用于研究目的)。我正在尝试实现加载/保存功能,其中包括将游戏的每个数据保存在文件中,并且用户可以重新加载之后保存的游戏。

在游戏中,每个玩家都有一个国家级,每个国家都继承自Nation。目前,我只在基类ISerializable上应用Nation接口,因为子类只有方法覆盖,没有新的属性可以序列化。

[Serializable()]
public abstract class Nation : ISerializable 
{
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        // save attributes
    }

    public Nation() { } // default constructor, to be able to do "new NationDwarf()" for example.

    // Deserialization constructor.
    public Nation(SerializationInfo info, StreamingContext ctxt)
    {
        // retrieve attributes
    }
}

public class NationDwarf : Nation {
    // some methods override
}
public class NationViking : Nation {
    // some methods override
}

储蓄似乎很好。但是,当我尝试使用此方法检索数据(反序列化)时,我得到一个异常(第一个玩家有一个NationDwarf):

  

SerializationException

     

缺少构造函数来反序列化'SmallWorld.NationDwarf'类型的对象。

所以,我的问题是:我是否需要为每个子类指定,它是可序列化的,并重新定义每个方法(GetObjectData和构造函数)?有没有办法保持多态性并序列化每个子类,当然能够在反序列化时获得正确的类型?

我没有找到任何解决方案,除了重新定义每个子类的序列化方法,这有点重......

谢谢,

2 个答案:

答案 0 :(得分:4)

简短版:是的。如果您实现了ISerializable,那么您的实现应该是虚拟的,并且被每个(以及每个)子类重写。

选项:

  • 使用BinaryFomatter,实现ISerializable,然后执行
  • 使用BinaryFormatter但不实现ISerializable
  • 不要使用BinaryFormatter

我不介意说我通常提倡最后一个选项。 BinaryFormatter有......扭结。我个人使用protobuf-net,但是:我有偏见(我是作者)

答案 1 :(得分:3)

您只需提供序列化构造函数并在基类中创建GetObjectData虚拟,以便在子类中覆盖它。

public NationDwarf(SerializationInfo info, StreamingContext context)
    : base(info, context)
{
}

当ISerializable接口从基类传递时,运行时仍然需要知道如何专门创建派生类的实例。