3

DataContractSerializer双方向エンティティをシリアル化する方法を理解するために、サンプルWCF​​サービスを実装しています。私は次のDataContractsを持っています。

[DataContract]
public class Process
{
    [DataMember]
    public string ProcessName { get; set; }
    [DataMember]
    public string Memory { get; set; }
    [DataMember]
    public User UserOfProcess { get; set; }
}

[DataContract]
public class User
{
    [DataMember]
    public string UserID { get; set; }
    [DataMember]
    public string UserName { get; set; }
    [DataMember]
    public List<Process> ProcessesOfUser { get; set; }
}

お気づきかもしれませんが、そのUser数は順番に関連付けられていますProcessProcessUser

  [OperationContract]
  User GetUser();

WCFTestClientからこのメソッドを実行すると、例外が発生します。これは、UserでProcessOfUserをシリアル化するたびに、trunでUserが再度シリアル化されるためです。

これを回避するには、Process[DataContract]のUserOfProcessからDataMember属性を削除します。正常に動作します。

私の質問は
1です。それはこの問題を解決する正しい方法ですか、それともIs there some other way to this[IgnoreDataMember]また、シリアル化を回避するための属性も見つけました。2.プログラムで属性
を追加または削除できますか?[DataMember]

4

1 に答える 1

3

[IsReference]属性を使用して、循環依存関係を解決するようにWCFに指示できます。

しかし、これを自分でビジネスオブジェクトに使用した後、非常に多くの問題が発生し、代わりに明示的なDTOを使用することになり、循環参照を省略して、実行したことを効果的に実行しました。DTOがビジネスオブジェクトに変換されたときに、クライアント側で参照を再度接続します。

ただし、IsReferenceは、単純なオブジェクトグラフには問題ありません。

編集:DTOについて

私が言ったように、私はもともとネットワークを介してドメインオブジェクトをシリアル化しましたが、最終的にはあまりにも厄介になりました。

まず、永続性のために同じオブジェクトをシリアル化するため、シリアル化のニーズが競合することになりましたが、主にDataContractSerializerがコンストラクターを呼び出さないため、オブジェクトが有効である保証はありません。メンバーがnullでないことを確認するための大きな[OnDeserialized]メソッドを使用することになりました。コレクションメンバーでこれを行うと、WCFがオブジェクトグラフをシリアル化する方法が原因で、大きな問題が発生しました。

DTOを使用すると、すべてがなくなり、サービスで何が起こっているかを正確に示す非常にクリーンなオブジェクトが公開されます。DTOを取得すると、奇妙な半シリアル化された状態ではなく、すべてが適切に配置されていることを認識してマッピングを実行できます。ドメインオブジェクトが本当に単純な場合は、それでうまくいくかもしれませんが、私は、苦痛が生じた後は、個人的にはお勧めしません。

DTOはばかげて単純です:

[DataContract]
public class UserProcessesDTO
{
    [DataMember] public string       UserID          { get; set; }
    [DataMember] public string       UserName        { get; set; }
    [DataMember] public ProcessDTO[] Processes       { get; set; }
}

[DataContract]
public class ProcessDTO
{
    [DataMember] public string       ProcessName     { get; set; }
    [DataMember] public string       Memory          { get; set; }
}

私のすべてのコレクションは、単純な配列としてネットワーク上を通過します。ビジネスオブジェクトの辞書などは、シリアル化しようとするのではなく、クライアント側でクリーンに構築されます。

于 2012-06-11T10:35:17.830 に答える