11

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

[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方法中使用的方法 ,分别用于在 中存储和检索 XML 字符串。.FromXml.OnSerializing.OnDeserializedxmlof3rdPartyData

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

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

4

1 回答 1

10

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

.NET 问题的一半

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

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

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

我的一半问题

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

可是等等...

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

我已经编写了一个测试用例来演示这一切。如果我做错了什么,我会很感激这样说的反馈,否则我可能会将其发布在 MSDN 论坛上或作为 Connect 错误。在任何人提出建议之前,由于在 SO 其他地方发布的所有各种原因,我已经计划离开BinaryFormatter一段时间了,我只是有更重要的事情要处理。

编辑:显然这个错误是一年半前提交的。

于 2012-07-13T01:09:09.817 回答