WCFの逆シリアル化には、いくつかの魔法があります。コンストラクターを呼び出さずに、データコントラクト型のインスタンスをどのようにインスタンス化しますか?
たとえば、次のデータコントラクトについて考えてみます。
[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
}
DataContractSerializer
を介してこのオブジェクトのインスタンスを取得すると、フィールド_wasConstructorCalled
はfalse
です。
では、WCFはこれをどのように行うのでしょうか。これは他の人も使用できるテクニックですか、それとも私たちから隠されていますか?
FormatterServices.GetUninitializedObject()
は、コンストラクターを呼び出さずにインスタンスを作成します。 Reflector を使用し、コア.Netシリアル化クラスのいくつかを調べて、このクラスを見つけました。
以下のサンプルコードを使用してテストしましたが、うまく機能しているようです。
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
はい、FormatterServices.GetUninitializedObject()が魔法の源です。
特別な初期化を行う場合は、こちらをご覧ください。 http://blogs.msdn.com/drnick/archive/2007/11/19/serialization-and-types.aspx