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?
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
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