不总是调用OnSerializing/OnSerialized方法

Spe*_*kim 9 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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

Spe*_*kim 9

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

.NET的一半问题

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

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

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

我的一半问题

简单地说,我忘了在我GetHashCodeD班级中包含非序列化字段,所以我遇到了冲突.我知道,愚蠢的错误不知道我是怎么错过它的.

可是等等...

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

我写了一个测试用例来演示这一切.如果我正在做任何明显错误的事情,我会很感激反馈这样说,否则我可能会在MSDN论坛上发布这个或作为Connect错误.在任何人提出建议之前,我已经计划在BinaryFormatter一段时间内切换掉所有在SO上发布的各种原因,我只是有更重要的事情需要处理.

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