メッセージからの復元時はデータコントラクトのコンストラクタが呼ばれない

WCF の通信で、データコントラクトをメッセージからオブジェクトに復元する際、コンストラクタが呼ばれません。値は DataMember 属性のついたプロパティの setter を使って設定されます。

例えば、次のようなデータコントラクトだと、復元時に例外が発生します。

[DataContract]
public class Foo
{
    // 宣言と同時に初期化しても…
    private Hashtable _property = new Hashtable();

    [DataMember]
    public string Code
    {
        get
        {
            return _property["Code"] as string;
        }
        set
        {
            // _property は null なので例外が発生してしまう
            _property["Code"] = value;
        }
    }
}

コンストラクタが呼ばれないので、_property は初期化されず null になってしまいます。そのため、値を設定するときに NullReferenceException が発生。

試しに、次のようにしたら回避できました。

[DataContract]
public class Foo
{
    private Hashtable _property = new Hashtable();

    [DataMember]
    public string Code
    {
        get
        {
            _property = _property ?? new Hashtable();
            return _property["Code"] as string;
        }
        set
        {
            // _property が null なら生成する
            _property = _property ?? new Hashtable();
            _property["Code"] = value;
        }
    }
}

無理やりですね。この手法はお勧めしません。

コレクションや DataRow など、何かをラップしたデータコントラクトを作るのは避けた方がいいです。データコントラクトは値を格納するだけの、シンプルな設計にしましょう。