【问题标题】:How do I deserialize old data for a type that has changed?如何反序列化已更改类型的旧数据?
【发布时间】:2010-11-18 15:32:20
【问题描述】:

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

[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,但是这个类有很多属性以及数百个继承类,我也必须实现它。

我想在反序列化期间更改旧数据以匹配当前结构,或者有一种干净的方式来升级旧数据。

【问题讨论】:

    标签: c# serialization binary-serialization


    【解决方案1】:

    以不同的名称添加新的 _fieldErrors,例如 _fieldErrors2,并将其命名为 [Optional]。然后实现一个[OnDeserialized] 方法,将数据从_fieldErrors 复制到_fieldErrors2(如果存在),并清除_fieldErrors。

    【讨论】:

    • 这为我的需求提供了最现实的方法,但我最终走上了不同的道路。
    【解决方案2】:

    如果数据仅在内部使用,我的第一个想法是编写一些简单的一次性代码,使用旧的“NameValueCollection”反序列化二进制数据,将其映射到字典并重新序列化。即使处理所有数据需要几天时间,在新代码上实施补丁以支持旧数据似乎也不值得。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-06
          • 2019-07-01
          • 1970-01-01
          • 2020-03-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多