gpt4 book ai didi

c# - 如何用新的 ISerializable 类替换遗留类

转载 作者:行者123 更新时间:2023-11-30 21:54:03 26 4
gpt4 key购买 nike

我们有一个遗留类A,它是[Serializable],但不是ISerializable。由于各种原因,必须修补此类以实现 ISerializable。

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

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

最佳答案

方案一

首先,更改项目的汇编版本。

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

为游戏存档数据创建一个新类型。

// 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
}
}

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

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

你可以这样使用它:

// the saveStream can contain either the old other the new format
BinaryFormatter bf = new BinaryFormatter() { Binder = new SavegameBinder() };
SavegameNew data = (SavegameNew)bf.Deserialize(saveStream);

解决方案2

使用此解决方案,您无需将 Savegame 映射到 SavegameNew。如果不更改程序集版本,则甚至不需要 binder 类。

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

// The legacy savegame data
[Serializable]
public class Savegame: IObjectReference
{
// ... the legacy fields

public object GetRealObject(StreamingContext context)
{
return new SavegameNew(...);
}
}

关于c# - 如何用新的 ISerializable 类替换遗留类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33544378/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com