Deserialization of optional fields from BinaryFormatter

二次信任 提交于 2019-12-30 10:08:10

问题


I have an application that serializes data using BinaryFormatter. A member was added to the class that was serialized from one version to the next without changing the class name. Code was added to handle the possible absence of the added member in old serialized files:

private void readData(FileStream fs, SymmetricAlgorithm dataKey)
{
    CryptoStream cs = null;

    try
    {
        cs = new CryptoStream(fs, dataKey.CreateDecryptor(),
            CryptoStreamMode.Read);
        BinaryFormatter bf = new BinaryFormatter();

        string string1 = (string)bf.Deserialize(cs);
        // do stuff with string1

        bool bool1 = (bool)bf.Deserialize(cs);
        // do stuff with bool1

        ushort ushort1 = (ushort)bf.Deserialize(cs);
        // do stuff with ushort1

        // etc. etc. ...

        // this field was added later, so it may not be present
        // in the serialized binary data.  Check for it, and if
        // it's not there, do some default behavior

        NewStuffIncludedRecently newStuff = null;

        try
        {
            newStuff = (NewStuffIncludedRecently)bf.Deserialize(cs);
        }
        catch
        {
            newStuff = null;
        }

        _newStuff = newStuff != null ?
                new NewStuffIncludedRecently(newStuff) :
                new NewStuffIncludedRecently();
    }
    catch (Exception e)
    {
        // ...
    }
    finally
    {
        // ...
    }
}

The point I'm at now is that I'd really like to just rinse and repeat with another member I'd like to add, which would mean I'd add another field and try-catch block similar to that for NewStuffIncludedRecently.

I had thought of just making the entire class [Serializable] but wouldn't that break compatibility with the old serialized data?

My main concern is that I'm not clear how the deserialization works. If I add in handling for another optional field similarly to above, will it work? What are other options I have for handling these changes better?

Thanks in advance as always.


回答1:


If you mark the new fields with [OptionalField] it should work, but I have heard reports of flakiness in some cases. I can't say for sure, since I avoid BinaryFormatter, because it has so many issues when versioning :) (plus, it isn't as "tight" as some alternatives, and has severe issues if you want to go cross-platform, or to CF/SL etc)

If you are implementing ISerializable, you might try:

foreach(SerializationEntry entry in info) {
    switch(entry.Name) {
         case "Name": Name = (string)info.Value;
         case "Id": Id = (int)info.Value;
         ...
    }
}

But again, must stress - this is doing things the hard way :p With this approach, you only process the data that is actually there.



来源:https://stackoverflow.com/questions/8245501/deserialization-of-optional-fields-from-binaryformatter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!