none
WCF - DataContractのプロパティ内での他クラスのインスタンス作成 RRS feed

  • 質問

  • WCFで以下のようなDataContract「ABC」を定義しています。
    ABCのCheckTypeプロパティで他クラスのコンストラクタを呼び出し、
    そのインスタンスをHogeプロパティに設定しています。

    質問:
    CheckTypeプロパティでHogeAのインスタンスを設定後、
    HogeプロパティからHogeA#Nameに「あいう」を設定したのですが、
    クライアント側でデシリアライズした結果、HogeプロパティのNameがクリアされていました。
    値を保持したままデシリアライズするには、どのような方法があるでしょうか?
    (補足)
    ・デシリアライズにはDataContractJsonSerializerを使用しています。
    ・CheckTypeプロパティのHoge = new HogeA();をコメントアウトし、ABCのコンストラクタでHoge = new HogeA()を記述したら、
     デシリアライズ後も値が保持されていました。

    [DataContract]
    public class ABC
    {
    	public enum CheckTypeKind
    	{
    		A = 0,
    		B
    	}
    
    	private CheckTypeKind _checkTypeKind;
    	[DataMember]
    	public CheckTypeKind CheckType
    	{
    		get { return _checkTypeKind; };
    		set
    		{
    			_checkTypeKind = value;
    			switch (value)
    			{
    				case CheckTypeKind.A:
    					Hoge = new HogeA();
    					break;
    				case CheckTypeKind.B:
    					Hoge = new HogeB();
    					break;
    			}
    		}
    	}
    	
    	[DataMember]
    	public Hoge Hoge { get; set; }
    }
    
    [DataContract]
    public HogeA : Hoge
    {
    	[DataMember]
    	public string Name { get; set; }
    	
    	HogeA()
    	{
    		Name = string.Empty();
    	}
    }
    
    [DataContract]
    public HogeB : Hoge
    {}
    



    • 編集済み holi_s 2015年5月1日 7:04
    2015年5月1日 7:01

回答

  • CheckType の setter において、Hoge がすでに目的の型になっていれば代入しないというコードで何とかならないでしょうか?(実験できていないので外していたらすみません)
    今のコードだと、同じ CheckType をセットしても内部の状態が変わるという、プロパティとしては予想できない動きを実装していることも理由です。

    おそらくですが、デシリアライズの流れで先に Hoge プロパティが set され、次に CheckType プロパティが set されることで、Hoge プロパティの中身が失われているのではないかと。
    順番を制御するのは難しいですし、今のコードから最小の差分を考えるなら、Hoge プロパティの中身の型を is で調べてから代入する・しないを分岐させるべきかなと思いました。

    (個人的には Hoge プロパティをどのように使うのだろうと疑問を感じます。ダウンキャストせずに済む作りであれば良いのですが…)

    • 回答としてマーク holi_s 2015年5月1日 9:32
    2015年5月1日 9:10
    モデレータ

すべての返信

  • CheckType の setter において、Hoge がすでに目的の型になっていれば代入しないというコードで何とかならないでしょうか?(実験できていないので外していたらすみません)
    今のコードだと、同じ CheckType をセットしても内部の状態が変わるという、プロパティとしては予想できない動きを実装していることも理由です。

    おそらくですが、デシリアライズの流れで先に Hoge プロパティが set され、次に CheckType プロパティが set されることで、Hoge プロパティの中身が失われているのではないかと。
    順番を制御するのは難しいですし、今のコードから最小の差分を考えるなら、Hoge プロパティの中身の型を is で調べてから代入する・しないを分岐させるべきかなと思いました。

    (個人的には Hoge プロパティをどのように使うのだろうと疑問を感じます。ダウンキャストせずに済む作りであれば良いのですが…)

    • 回答としてマーク holi_s 2015年5月1日 9:32
    2015年5月1日 9:10
    モデレータ
  • 返信ありがとうございます。

    おっしゃる通り、setterで同値チェックを入れたところ、
    値が保持されました。

    また、Hogeプロパティについてですが、
    リフレクションを使用してインスタンスを取得し、
    HogeAインスタンスのプロパティもまたリフレクションを使用して取り出し、値を設定するということをしています。
    あるテキストファイルの内容をクラスに落とし込むということを汎用的に実現したいためにこのような方法を取っています。
    実際にはプロパティにカスタム属性を付けて色々やっています。

    デシリアライズ時のデバッグができなくハマっていましたが、
    おかげさまで解決できました。
    ありがとうございました。


    2015年5月1日 9:32