How does WCF deserialization instantiate objects without calling a constructor?

C#.NetWcfReflectionSerialization

C# Problem Overview


There is some magic going on with WCF deserialization. How does it instantiate an instance of the data contract type without calling its constructor?

For example, consider this data contract:

[DataContract]
public sealed class CreateMe
{
   [DataMember] private readonly string _name;
   [DataMember] private readonly int _age;
   private readonly bool _wasConstructorCalled;

   public CreateMe()
   {
      _wasConstructorCalled = true;
   }

   // ... other members here
}

When obtaining an instance of this object via DataContractSerializer you will see that the field _wasConstructorCalled is false.

So, how does WCF do this? Is this a technique that others can use too, or is it hidden away from us?

C# Solutions


Solution 1 - C#

FormatterServices.GetUninitializedObject() will create an instance without calling a constructor. I found this class by using Reflector and digging through some of the core .Net serialization classes.

I tested it using the sample code below and it looks like it works great:

using System;
using System.Reflection;
using System.Runtime.Serialization;

namespace NoConstructorThingy
{
    class Program
    {
        static void Main()
        {
            // does not call ctor
            var myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass));

            Console.WriteLine(myClass.One); // writes "0", constructor not called
            Console.WriteLine(myClass.Two); // writes "0", field initializer not called
        }
    }

    public class MyClass
    {
        public MyClass()
        {
            Console.WriteLine("MyClass ctor called.");
            One = 1;
        }

        public int One { get; private set; }
        public readonly int Two = 2;
    }
}

http://d3j5vwomefv46c.cloudfront.net/photos/large/687556261.png">

Solution 2 - C#

Yes, FormatterServices.GetUninitializedObject() is the source of the magic.

If you want to do any special initialization, see this. http://blogs.msdn.com/drnick/archive/2007/11/19/serialization-and-types.aspx

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDrew NoakesView Question on Stackoverflow
Solution 1 - C#Jason JacksonView Answer on Stackoverflow
Solution 2 - C#AaronMView Answer on Stackoverflow