如何用新的ISerializable类替换遗留类

时间:2015-11-05 12:20:00

标签: c# .net serialization c++-cli binaryformatter

我们的遗留类A[Serializable],但不是ISerializable。 由于其他原因,必须修补此类以实现ISerializable。

问题是我们仍然需要能够加载旧的保存文件,这些文件使用.NET的默认实现来进行类A的序列化。 换句话说,在加载旧的savefiles时,类A必须像旧版本一样反序列化,然后转换为类A的新版本,这样当再次保存时,我们的新实现{{ 1}}被使用。

在不破坏向后兼容性的情况下修补类ISerializable的最佳方法是什么?

1 个答案:

答案 0 :(得分:3)

解决方案1 ​​

首先,更改项目的程序集版本。

AsEnumerable

为savegame数据创建一个新类型。

// AssemblyInfo.cs:
[assembly: AssemblyVersion("2.0.0.0")]

现在您需要一个将旧格式映射到新格式的binder类:

// The legacy savegame data. Keep it as it is.
[Serializable]
public class Savegame
{
    // ... the legacy fields
}

// The new savegame data. This implements ISerializable
[Serializable]
public class SavegameNew : Savegame, ISerializable
{
    // this constructor will execute on deserialization. You will deserialize
    // both the legacy and new types here.
    private SavegameNew(SerializationInfo info, StreamingContext context)
    {
        foreach (SerializationEntry entry in info)
        {
            // you can iterate the serialized elements like this
            // if this is a new format you will get the new elements, too
        }
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        // custom serialization of the new type
    }
}

你可以像这样使用它:

internal class SavegameBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        // Of course, use the assembly version of the old version here.
        // You don't even need to change the assembly version, though than can lead to ambiguity
        AssemblyName asmName = new AssemblyName(assemblyName);
        if (asmName.Version == new Version(1, 0, 0, 0) && typeName == typeof(Savegame).FullName)
            return typeof(SavegameNew);

        // otherwise we do not change the mapping
        return null;
    }
}

解决方案2

使用此解决方案,您无需将// the saveStream can contain either the old other the new format BinaryFormatter bf = new BinaryFormatter() { Binder = new SavegameBinder() }; SavegameNew data = (SavegameNew)bf.Deserialize(saveStream); 映射到Savegame。如果不更改程序集版本,则甚至不需要binder类。

如果您更改了程序集版本,SavegameNew应返回新程序集的SavegameBinder类型。遗留Savegame应该实现Savegame接口,因此一旦反序列化,它就可以返回IObjectReference个实例。

SavegameNew