简体   繁体   English

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

[英]How do I deserialize old data for a type that has changed?

I have data that has been stored using binary serialization for the following class: 我有使用二进制序列化为以下类存储的数据:

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

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

    ...
}

At some point, the class was changed to this: 在某些时候,课程改为:

[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; }
    }

    ...
}

This is causing issues deserializing old data. 这导致了对旧数据进行反序列化的问题。

My first thought was to implement ISerializable , but this class has numerous properties as well as hundreds of inheriting classes that I would have to implement this for as well. 我的第一个想法是实现ISerializable ,但是这个类有许多属性以及数百个继承类,我也必须实现它。

I would like to either change the old data to match the current structure during deserialization or have a clean way of upgrading the old data. 我想在反序列化期间更改旧数据以匹配当前结构,或者有一种干净的升级旧数据的方法。

Add the new _ fieldErrors under a different name, say _fieldErrors2 , and make it [Optional] . 以不同的名称添加新的_ fieldErrors ,例如_fieldErrors2 ,并将其_fieldErrors2 [Optional] Then implement an [OnDeserialized] Method that copies the data from _fieldErrors to _fieldErrors2 (if present), and clears _fieldErrors. 然后实现一个[OnDeserialized]方法,将_fieldErrors的数据_fieldErrors_fieldErrors2 (如果存在),并清除_fieldErrors。

If the data is only used internally, my first thought would be to write some simple throw-away code to de-serialize your binary data using the old "NameValueCollection", map it to a Dictionnary and re-serialize it. 如果数据仅在内部使用,我首先想到的是编写一些简单的丢弃代码,使用旧的“NameValueCollection”对二进制数据进行反序列化,将其映射到Dictionnary并重新序列化。 Even if it'll take a few days to process all the data, it doesn't seem worth it to implement a patch on your new code to support the old data. 即使处理所有数据需要几天时间,但在新代码上实现补丁以支持旧数据似乎也不值得。

Even if it's not only used internally, an importer seems like the simplest way to go. 即使它不仅在内部使用,进口商似乎是最简单的方法。

Adding to OlivierD's good advice, I'd suggest you define both classes but initially try to deserialize as the current version. 添加OlivierD的好建议,我建议您定义两个类,但最初尝试反序列化为当前版本。 In your catch block, deserialize it as the legacy version, then upgrade it to the current one and save it back. 在catch块中,将其反序列化为旧版本,然后将其升级到当前版本并保存回来。 When no instances of the legacy version exist, you can remove the code. 如果不存在旧版本的实例,则可以删除代码。

After investigating a few options, I made the following conclusions: 在研究了几个选项之后,我做出了以下结论:

Ideally I would be able to access the value from the original NameValueCollection and manually convert it to Dictionary<string, string> . 理想情况下,我可以访问原始NameValueCollection的值并手动将其转换为Dictionary<string, string> The only way to do this would be to implement ISerializable , but this posed two major issues: matching up to the naming of the legacy data and the inclusion of serialization logic for all inheriting classes (of which there are hundreds). 实现这一目标的唯一方法是实现ISerializable ,但这提出了两个主要问题:匹配遗留数据的命名和包含所有继承类(其中有数百个)的序列化逻辑。

Effectively, this put me in a bind. 实际上,这让我陷入困境。 Fortunately, I was able to determine that this field is really only used as a summary of form validation errors and shouldn't be getting serialized in the first place, therefore I have excluded it from serialization. 幸运的是,我能够确定此字段实际上仅用作表单验证错误的摘要,并且不应该首先进行序列化,因此我将其排除在序列化之外。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM