Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>Now both methods get called before the constructor gets called</p> </blockquote> <p>No, the order is:</p> <ul> <li>OnDeserializingMethod</li> <li>.ctor</li> <li>OnDeserializedMethod</li> </ul> <blockquote> <p>And how can a (non-static) method be called before any constructor has been executed? </p> </blockquote> <p>Because it cheats and lies; it doesn't create the object with the constructor; no - really. It uses <code>FormatterServices.GetUninitializedObject</code> to allocate vanilla empty space. And then if there is a custom deserialization constructor it invokes the constructor <em>over the top of that</em> object. Nasty. Like this, basically:</p> <pre><code>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]); </code></pre> <p>IMO they probably should have made this a second method on the <code>ISerializable</code> 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.</p> <p>Example output:</p> <pre><code>.ctor: MyClass &gt; serializing OnSerializingMethod: MyClass GetObjectData: MyClass OnSerializedMethod: MyClass &lt; serializing &gt; deserializing OnDeserializingMethod: MyClass .ctor: MyClass OnDeserializedMethod: MyClass &lt; deserializing </code></pre> <p>Example code:</p> <pre><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("&gt; serializing"); ser.Serialize(ms, orig); System.Console.WriteLine("&lt; serializing"); ms.Position = 0; System.Console.WriteLine("&gt; deserializing"); ser.Deserialize(ms); System.Console.WriteLine("&lt; deserializing"); } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload