反序列化时忽略过时字段

3
我整天都在寻找一种方法来实现这个,但是没有结果...
我正在尝试反序列化一个对象。当我对其进行序列化时,我有一个名为(假设)obsoleteBool的布尔值。在类的新版本中,我删除了这个bool,并且在反序列化时出现了错误(字段“obsoleteBool”未找到)。
在旧版和新版类之间添加新字段非常容易,即使不使用[OptionalField]属性...但是,如何处理在旧版和新版类之间删除字段?

我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
实现 ISerializable。这需要时间和精力,但您将拥有更多控制权(而且您可以 - 大致地 - 管理版本控制)。 - Adriano Repetti
你用什么进行序列化? - ahruss
我希望我的类可以被用户扩展。据我所知,使用ISerializable将要求他们管理他们将创建的新变量的序列化。当我使用[Serializable]属性时,他们可以创建新变量,而无需执行任何其他操作即可保存。@ahruss:我正在使用BinaryFormatter进行序列化。 - Ryan Pergent
1个回答

0

有3种可能的解决方案:

  • 最简单的解决方案:将旧字段添加到类的新版本中
  • 自定义代码:实现自定义反序列化器
  • 额外的工作:编写一个转换程序,遍历所有序列化的类,使用旧格式读取它们,然后使用新类定义重新序列化它们。

在业务价值方面,第一种选项可能更可取。


因为用户将扩展我的类并且可能在序列化之间进行多次迭代,所以我希望找到最干净的解决方案。保留过时字段可能会使代码变得极其混乱,更不用说那些可能由于此而选择不重命名变量并最终出现不匹配名称或类似问题的人。自定义序列化程序能否自动考虑用户创建的新字段?关于转换程序,如果我在尝试打开类时遇到“缺少字段”错误消息,我该怎么办? - Ryan Pergent
使用ISerializable,您可以管理派生类中的字段(就像BinaryFormatter一样)。当然,这不是最好的解决方案,但您可以通过反射来实现它。要进行转换,您必须部署两个版本(带有和不带有额外字段的版本),在一个AppDomain中反序列化,在第二个AppDomain中将反序列化的数据移动到新格式中。非常困难。我认为整个重点是,序列化不是用于数据文件(具有版本控制)的工具。它对许多事情很有用,但不适用于此(因为经过几个版本后,它会使您的代码变得混乱,如果您曾经更改了层次结构...)。 - Adriano Repetti
我现在正在尝试实现ISerializable方法。唯一的不便之处是,我需要在所有继承自默认类的类中都有一个带有SerializationInfo和StreamingContext的构造函数(我有很多这样的类)。但与无法删除变量相比,这只是一个小缺陷。然而,我面临另一个问题:我使用反射来获取和保存所有字段,但我只需要获取[Serializable]字段。BindingFlags似乎没有提供这样的过滤...是否有人知道如何以这种方式过滤我的字段? - Ryan Pergent
1
我成功地使用System.Reflection.FieldInfo中的IsNotSerialized过滤掉它们 :) 非常感谢你们的帮助,我想现在我将能够实现我想要的了。 - Ryan Pergent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接