web-dev-qa-db-fra.com

Comment la désérialisation WCF instancie-t-elle des objets sans appeler de constructeur?

Il y a de la magie avec la désérialisation WCF. Comment instancie-t-il une instance du type de contrat de données sans appeler son constructeur?

Par exemple, considérez ce contrat de données:

[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
}

Lorsque vous obtenez une instance de cet objet via DataContractSerializer, vous verrez que le champ _wasConstructorCalled est false.

Alors, comment WCF fait-il cela? Est-ce une technique que d'autres peuvent également utiliser, ou est-elle cachée loin de nous?

78
Drew Noakes

FormatterServices.GetUninitializedObject() créera une instance sans appeler de constructeur. J'ai trouvé cette classe en utilisant Reflector et en fouillant dans certaines des classes de sérialisation de base .Net.

Je l'ai testé en utilisant l'exemple de code ci-dessous et il semble que cela fonctionne très bien:

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

100
Jason Jackson

Oui, FormatterServices.GetUninitializedObject () est la source de la magie.

Si vous souhaitez effectuer une initialisation spéciale, voyez ceci. http://blogs.msdn.com/drnick/archive/2007/11/19/serialization-and-types.aspx

19
AaronM