Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Deserialisation with OnDeserializing and OnDeserialized

Tags:

I use a simple class that is serializable. It has a constructor for the deserialization:

protected MyClass(SerializationInfo info, StreamingContext context) 

and a GetObjectData method for serialisation. It works fine.

Now I added two methods to monitor the deserialisation:

        [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());     } 

and was wondering in which order these methods are beeing called. Now both methods get called before the constructor gets called. How is that possible, and why isn't the "OnDeserialized" method called after the (deserialization-) constructor has been called? And how can a (non-static) method be called before any constructor has been executed? (I am using a BinaryFormatter)

like image 875
Gerhard Avatar asked Aug 22 '13 09:08

Gerhard


People also ask

What is the difference between serialize and deserialize C#?

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.

What is the difference between deserialize and serialize?

Serialization is a mechanism of converting the state of an object into a byte stream. Deserialization is the reverse process where the byte stream is used to recreate the actual Java object in memory. This mechanism is used to persist the object. The byte stream created is platform independent.

How does deserialization work in C#?

December 17, 2021. Serialization in C# is the process of bringing an object into a structure that is composed in memory. Deserialization is the opposite of serialization. It involves retrieving the serialized object so that it can be stored in memory.

What is serialization and deserialization medium?

The process of converting a structured object into a sequence of bytes which can be stored in a file system or database or sent through the network is called serialization. The reversed process is called deserialization, which means reconverting a sequence of bytes into a structured object.


1 Answers

Now both methods get called before the constructor gets called

No, the order is:

  • OnDeserializingMethod
  • .ctor
  • OnDeserializedMethod

And how can a (non-static) method be called before any constructor has been executed?

Because it cheats and lies; it doesn't create the object with the constructor; no - really. It uses FormatterServices.GetUninitializedObject to allocate vanilla empty space. And then if there is a custom deserialization constructor it invokes the constructor over the top of that object. Nasty. Like this, basically:

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 they probably should have made this a second method on the ISerializable interface, but for whatever reason: they didn't. A shame really: that would have made it more honest, and avoided people needing to remember to implement the custom constructor.

Example output:

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

Example code:

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");         }     } } 
like image 180
Marc Gravell Avatar answered Oct 27 '22 12:10

Marc Gravell