这是我在项目中序列化的结构:
[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字符串。
我最近遇到过一个问题,在某些未知的情况下(我到目前为止只能使用来自客户的序列化数据文件重现问题,首先报告此问题),我的{{1}当使用.OnSerializing
序列化到文件时,和.OnSerialized
方法只被调用57/160次(其中160是结构中D
个对象的总数)将BinaryFormatter
设置为D
的103 xmlOf3rdPartyData
个对象。使用描述here的方法克隆结构时(基本上与我用于序列化文件的方法相同),我看到null
/ .OnSerializing
的结果相同,但我的.OnSerialized
方法被称为完整的160次。
这段代码已经使用了好几个月没有问题(至少,据我所知),我仍然试图确定为什么现在发生这种情况而不是更早。我在调试时没有看到任何第一次机会异常,并且我在方法开始时的断点根本没有被击中超过57次。关于为什么会发生这种情况或如何修复它的任何想法?
答案 0 :(得分:9)
经过几天的挖掘,我发现问题既是我的错也是.NET Framework中可能存在的错误。
在我的OnSerializing
方法的堆栈跟踪中,我偶然发现RegisterObject
中的System.Runtime.Serialization.SerializationObjectManager
方法,它确定是否在对象中调用任何OnSerializing
方法被序列化。它以两种方式确定这一点(这是基于.NET Reflector的反编译代码):
OnSerializing
方法可供调用BinaryFormatter.Serialize
的调用中) 2号是问题孩子。它通过将它们存储为Hashtable
中的对象/布尔对来跟踪已经看到的对象(当然,它使用GetHashCode
)。如果其中任何一个为假,则对象的OnSerializing
方法不被调用。这显然在绝大多数情况下都能正常工作(否则微软会在某些时候修复它,对吧?),除了我似乎偶然发现的那个。
简单地说,我忘了在我的GetHashCode
类D
中包含非序列化字段,因此我遇到了冲突。我知道,这个愚蠢的错误不知道我是怎么错过的。
......这不是说这根本不是.NET的错,只是我自己的错吗?不,这就是原因。我希望无论如何都会在100%的时间内调用OnSerializing
和OnSerialized
方法。没有文档在哪里说不然。当没有发生这种情况时,我的对象没有正确序列化,最终我花费的时间比想要解决谜团更多。即使两个相同的对象被有目的地序列化,它们显然也不会指向Stream
中的相同二进制数据/位置,因此它们不会反序列化。 我认为这是一个错误,而不是一个功能。
我写了test-case来证明这一切。如果我正在做任何明显错误的事情,我会很感激反馈这样说,否则我可能会在MSDN论坛上发布这个或者作为Connect错误。在有人建议之前,我已经计划在一段时间内从BinaryFormatter
切换出来,因为在其他地方发布的所有各种原因,我只是有更重要的事情需要处理。
修改:显然this bug已在一年半前提交。