如何针对已更改的类型反序列化旧数据?

时间:2009-08-11 14:34:19

标签: c# serialization binary-serialization

我有使用二进制序列化存储的数据用于以下类:

[Serializable]
public abstract class BaseBusinessObject
{
    private NameValueCollection _fieldErrors = new NameValueCollection();

    protected virtual NameValueCollection FieldErrors
    {
        get { return _fieldErrors; }
        set { _fieldErrors = value; }
    }

    ...
}

在某些时候,课程改为:

[Serializable]
public abstract class BaseBusinessObject
{
    private Dictionary<string, string> _fieldErrors = new Dictionary<string, string>();

    protected virtual Dictionary<string, string> FieldErrors
    {
        get { return _fieldErrors; }
        set { _fieldErrors = value; }
    }

    ...
}

这导致了对旧数据进行反序列化的问题。

我的第一个想法是实现ISerializable,但是这个类有很多属性以及数百个继承类,我也必须实现它。

我想在反序列化过程中更改旧数据以匹配当前结构,或者使用干净的方法升级旧数据。

4 个答案:

答案 0 :(得分:4)

使用其他名称添加新的fieldErrors,例如_fieldErrors2,并将其设为[Optional]。然后实现[OnDeserialized]方法,将数据从_fieldErrors复制到_fieldErrors2(如果存在),并清除_fieldErrors。

答案 1 :(得分:3)

如果数据仅在内部使用,我首先想到的是编写一些简单的丢弃代码,使用旧的“NameValueCollection”对二进制数据进行反序列化,将其映射到Dictionnary并重新序列化。即使处理所有数据需要几天时间,但在新代码上实现补丁以支持旧数据似乎也不值得。

即使它不仅在内部使用,导入器似乎也是最简单的方法。

答案 2 :(得分:2)

添加OlivierD的好建议,我建议您定义这两个类,但最初尝试反序列化为当前版本。在catch块中,将其反序列化为旧版本,然后将其升级到当前版本并保存回来。如果不存在旧版本的实例,则可以删除代码。

答案 3 :(得分:0)

在研究了几个选项之后,我做出了以下结论:

理想情况下,我可以访问原始NameValueCollection中的值并手动将其转换为Dictionary<string, string>。实现此目的的唯一方法是实现ISerializable,但这提出了两个主要问题:匹配遗留数据的命名和包含所有继承类(其中有数百个)的序列化逻辑。

实际上,这让我陷入困境。幸运的是,我能够确定该字段实际上仅用作表单验证错误的摘要,并且不应该首先进行序列化,因此我将其排除在序列化之外。