c# - 并不总是调用 OnSerializing/OnSerialized 方法

标签 c# serialization binaryformatter

这是我在项目中序列化的结构:

[Serializable]
class A : List<B> //root object being serialized

[Serializable]
class B
  + [A few serializable fields]
  + C customList

[Serializable]
class C : List<D>

[Serializable]
class D
  + [several serializable fields]
  |
  + [NonSerialized] nonserializable3rdPartyClass data
  + string xmlOf3rdPartyData
  |
  + [OnSerializing]
  + private void OnSerializing(StreamingContext context)
  |
  + [OnSerialized]
  + private void OnSerialized(StreamingContext context)
  |
  + [OnDeserialized]
  + private void OnDeserialized(StreamingContext context)

nonserializable3rdPartyClass 虽然没有标记为 [Serializable],但提供了 .ToXml.FromXml 方法我在 .OnSerializing.OnDeserialized 方法中分别使用了在 xmlof3rdPartyData 中存储和检索 XML 字符串。

我最近遇到了一个问题,在某些未知情况下(到目前为止,我只能使用来自首先报告该问题的客户的序列化数据文件来重现该问题),我的 .使用 时,OnSerializing.OnSerialized 方法仅被调用 57/160 次(其中 160 是结构中 D 对象的总数) >BinaryFormatter 序列化为一个文件,给我留下 103 个 D 对象,其中 xmlOf3rdPartyData 设置为 null。使用描述的方法克隆结构时 here (这与我用来序列化到文件的方法基本相同),我看到 .OnSerializing/.OnSerialized 的结果相同,但我的 .OnDeserialized 方法被调用了 160 次。

这段代码已经使用了几个月没有问题(至少,据我所知),我仍在尝试确定为什么现在而不是更早发生这种情况。我在调试时没有看到任何第一次机会异常,而且我在方法开始处的断点根本没有被击中超过 57 次。关于为什么会发生这种情况/如何解决它的任何想法?

最佳答案

经过几天的挖掘,我发现这个问题既是我的错,也是 .NET Framework 中可能存在的错误。

.NET 的一半问题

在查看我的 OnSerializing 方法的堆栈跟踪时,我发现了 System.Runtime.Serialization.SerializationObjectManager 中的 RegisterObject 方法,它决定是否调用正在序列化的对象中的任何 OnSerializing 方法。它以两种方式确定这一点(这是基于 .NET Reflector 的反编译代码):

  1. 该类是否有任何OnSerializing方法可以调用
  2. 这是一个以前看不见的对象吗(在对 BinaryFormatter.Serialize 的调用中)

2 号是问题 child 。它通过将对象作为对象/ bool 对存储在 Hashtable(当然使用 GetHashCode)中来跟踪已经看到的对象。如果其中任何一个为假,则调用对象的OnSerializing 方法。这显然在绝大多数情况下都能正常工作(否则微软会在某个时候修复它,对吧?),除了我似乎偶然发现的那个。

我的一半问题

很简单,我忘记在我的 D 类的 GetHashCode 中包含不可序列化的字段,所以我遇到了冲突。愚蠢的错误,我知道,不知道我是怎么错过的。

但是等等...

...这是否意味着这根本不是 .NET 的错,只是我自己的错?不,这就是原因。我希望 OnSerializingOnSerialized 方法无论如何都会被调用 100%。文档中没有其他地方说明。如果那没有发生,我的对象就没有正确序列化,我最终花费的时间比我想要解决谜团的时间要多得多。即使两个相同的对象被有目的地序列化,它们显然不会最终指向 Stream 中的相同二进制数据/位置,因此它们不会反序列化相同的对象。 我认为这是一个错误,而不是一个功能。

我写了一个test-case这证明了这一切。如果我做错了什么公然错误,我将不胜感激这样的反馈,否则我可能会将其发布在 MSDN 论坛上或作为 Connect 错误。在任何人提出建议之前,由于 SO 上其他地方发布的各种原因,我已经计划在一段时间内不再使用 BinaryFormatter,我只是有更重要的事情要处理。

编辑:显然this bug提交时间超过一年半。

关于c# - 并不总是调用 OnSerializing/OnSerialized 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11421761/

相关文章:

c# - 从BackgroundService创建DbContext租户时配置它

c# - NEST未建立索引

c# - 将表单文件转换为内存流时出错

java - Jackson 接口(interface)序列化

java - 无法在 scala 中使用 jackson fastxml 将 json 数组反序列化为类对象

c# - 如何使用 EntityFramework 处理数据库中实体的 Hashtable 属性

c# - 如何序列化 CustomLineCap 类的实例

c# - 是什么阻止了我的异步函数设置中的主线程?

c# - 跨 AppDomain 的自定义序列化

json - 如何编写 Serde Visitor 将字符串数组转换为 Vec<Vec<f64>>?