使用OnDeserializing和OnDeserialized进行.NET反序列化

我使用了一个可序列化的简单类。 它有一个反序列化的构造函数:

protected MyClass(SerializationInfo info, StreamingContext context) 

和一个用于序列化的GetObjectData方法。 它工作正常。

现在我添加了两种方法来监视反序列化:

  [OnDeserializing()] internal void OnDeserializingMethod(StreamingContext context) { System.Diagnostics.Trace.WriteLine("OnDeserializingMethod: " + this.GetType().ToString()); } [OnDeserialized()] internal void OnDeserializedMethod(StreamingContext context) { System.Diagnostics.Trace.WriteLine("OnDeserializedMethod: " + this.GetType().ToString()); } 

并且想知道这些方法的调用顺序。 现在,在调用构造函数之前调用这两个方法。 这怎么可能,为什么在调用(反序列化)构造函数后调用的“OnDeserialized”方法不被调用? 如何在执行任何构造函数之前调用(非静态)方法? (我正在使用BinaryFormatter)

现在,在调用构造函数之前调用这两个方法

不,订单是:

  • OnDeserializingMethod
  • .ctor
  • OnDeserializedMethod

如何在执行任何构造函数之前调用(非静态)方法?

因为它欺骗和谎言; 它不会使用构造函数创建对象; 不完全是。 它使用FormatterServices.GetUninitializedObject来分配vanilla空白空间。 然后,如果有自定义反序列化构造函数,它会调用该对象顶部的构造函数。 讨厌。 像这样,基本上:

 var obj = FormatterServices.GetUninitializedObject(typeof(MyClass)); var ctor = obj.GetType().GetConstructor( BindingFlags.Instance | BindingFlags.Public| BindingFlags.NonPublic, null, new[] { typeof(SerializationInfo), typeof(StreamingContext) }, null); ctor.Invoke(obj, new object[2]); 

IMO他们可能应该在ISerializable接口上将其作为第二种方法,但无论出于何种原因:他们没有。 真的很遗憾:这会使它更诚实,并避免人们需要记住实现自定义构造函数。

输出示例:

 .ctor: MyClass > serializing OnSerializingMethod: MyClass GetObjectData: MyClass OnSerializedMethod: MyClass < serializing > deserializing OnDeserializingMethod: MyClass .ctor: MyClass OnDeserializedMethod: MyClass < deserializing 

示例代码:

 using System; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; [Serializable] class MyClass : ISerializable { public MyClass() { Trace(); } protected MyClass(SerializationInfo info, StreamingContext context) { Trace(); } public void GetObjectData(SerializationInfo info, StreamingContext context) { Trace(); } void Trace([CallerMemberName] string caller = null) { System.Console.WriteLine("{0}: {1}", caller, GetType().Name); } [OnDeserializing()] internal void OnDeserializingMethod(StreamingContext context) { Trace(); } [OnDeserialized()] internal void OnDeserializedMethod(StreamingContext context) { Trace(); } [OnSerializing()] internal void OnSerializingMethod(StreamingContext context) { Trace(); } [OnSerialized()] internal void OnSerializedMethod(StreamingContext context) { Trace(); } static void Main() { using (var ms = new MemoryStream()) { var orig = new MyClass(); var ser = new BinaryFormatter(); System.Console.WriteLine("> serializing"); ser.Serialize(ms, orig); System.Console.WriteLine("< serializing"); ms.Position = 0; System.Console.WriteLine("> deserializing"); ser.Deserialize(ms); System.Console.WriteLine("< deserializing"); } } } 

调用的顺序取决于对象是序列化树的根还是对象的某个成员,它也在同一对象图中序列化。 我使用Marc Gravell提供的扩展示例获得以下输出:

 SerRoot.ctor SerMember.ctor > serializing SerRoot.OnSerializingMethod GetObjectData SerMember.OnSerializingMethod SerMember.GetObjectData SerRoot.OnSerializedMethod SerMember.OnSerializedMethod < serializing > deserializing SerRoot.OnDeserializingMethod SerMember.OnDeserializingMethod SerMember.OnDeserializedMethod SerMember.ctor(info, context) SerRoot.ctor(info, context) SerRoot.OnDeserializedMethod < deserializing 

请注意,在反序列化中,SerMember.ctor是在SerMember.OnDeserializedMethod之后调用的! 这是代码:

  static void Main(string[] args) { using (var ms = new MemoryStream()) { var orig = new SerRoot(); var ser = new BinaryFormatter(); System.Console.WriteLine("> serializing"); ser.Serialize(ms, orig); System.Console.WriteLine("< serializing"); ms.Position = 0; System.Console.WriteLine("> deserializing"); ser.Deserialize(ms); System.Console.WriteLine("< deserializing"); } } [Serializable] class SerRoot : ISerializable { public SerMember m; public SerRoot() { System.Console.WriteLine("SerRoot.ctor"); m = new SerMember(); } protected SerRoot(SerializationInfo info, StreamingContext context) { System.Console.WriteLine("SerRoot.ctor(info, context)"); m = info.GetValue("m", typeof(SerMember)) as SerMember; } public void GetObjectData(SerializationInfo info, StreamingContext context) { System.Console.WriteLine("GetObjectData"); info.AddValue("m", m); } [OnDeserializing()] internal void OnDeserializingMethod(StreamingContext context) { System.Console.WriteLine("SerRoot.OnDeserializingMethod"); } [OnDeserialized()] internal void OnDeserializedMethod(StreamingContext context) { System.Console.WriteLine("SerRoot.OnDeserializedMethod"); } [OnSerializing()] internal void OnSerializingMethod(StreamingContext context) { System.Console.WriteLine("SerRoot.OnSerializingMethod"); } [OnSerialized()] internal void OnSerializedMethod(StreamingContext context) { System.Console.WriteLine("SerRoot.OnSerializedMethod"); } } [Serializable] class SerMember : ISerializable { string text; public SerMember() { System.Console.WriteLine("SerMember.ctor"); text = "test"; } protected SerMember(SerializationInfo info, StreamingContext context) { System.Console.WriteLine("SerMember.ctor(info, context)"); text = info.GetString("text"); } public void GetObjectData(SerializationInfo info, StreamingContext context) { System.Console.WriteLine("SerMember.GetObjectData"); info.AddValue("text", text); } [OnDeserializing()] internal void OnDeserializingMethod(StreamingContext context) { System.Console.WriteLine("SerMember.OnDeserializingMethod"); } [OnDeserialized()] internal void OnDeserializedMethod(StreamingContext context) { System.Console.WriteLine("SerMember.OnDeserializedMethod"); } [OnSerializing()] internal void OnSerializingMethod(StreamingContext context) { System.Console.WriteLine("SerMember.OnSerializingMethod"); } [OnSerialized()] internal void OnSerializedMethod(StreamingContext context) { System.Console.WriteLine("SerMember.OnSerializedMethod"); } } 

[OnDeserializing]表示在反序列化之前调用的方法[OnDeserialized]表示在反序列化之后调用的方法

[OnDeserializing]方法充当反序列化的伪构造函数,它对初始化从序列化中排除的字段很有用:

[OnDeserializing]和[OnDeserialized]反序列化绕过所有正常构造函数以及字段初始值设定项。 如果每个字段都参与序列化,则这没什么影响,但如果通过[NonSerialized]排除某些字段,则可能会出现问题。

我从Albahari的书C#5.0中摘取了这篇文章的简介第713页,在网上查看了很多关于你的问题的例子和描述。

谢谢