5

私が見ることができることから、WCFを介して転送するデータの種類ごとに「特別な」データ型を作成する必要があるため、次のような共有クラスがある場合

public class District
{
    public long Id { get; set; }
    public string Name { get; set; }
}

WCFを使用してDistrictオブジェクトを送信したいので、データコントラクトを作成する必要があるため、新しいWCFクラスを作成する必要があります。

[DataContract]
public class WCFDistrict
{
    [DataMember]
    public long Id { get; set; }

    [DataMember]
    public string Name { get; set; }
}

そして、実装のWCFサービスでそれを使用するときは、あるオブジェクトから別のオブジェクトにデータを解析する必要があります。

public WCFDistrict GetDistrict(long id)
{
    var district = _districtRepository.GetDistrict(id);
    return new WCFDistrict {Id = district.Id, Name = district.Name};
}

それらの属性を持たずに、共有クラスをDataContractとして再利用する方法はありますか?または、共有できるクラスにインターフェイスを作成して、クラス間でキャストできるようにする必要がありますか?または何か3番目?

4

2 に答える 2

9

まず、DataContractを提供する必要はありません。WCFは、.Net 3.5 SP1以降を使用している限り、プレーンオールドクラスオブジェクト(POCO)を正しくシリアル化します。

次に、サーバー側とクライアント側の両方のプロジェクトで同じ物理クラスファイルを共有できます。この方法で直接共有される何百ものクラス(およびコード)を持つプロジェクトがあり、開発とテストの時間と労力を大幅に節約できます。

これを起動して実行するには、いくつかの手順が必要です(これをメモリから実行するため、答えを調整する必要がある場合があります)。

1)クライアント側で、VBを使用している場合は、クライアント側で使用するクラスと同じデフォルトの名前空間でプロジェクトを作成します(C#の場合、名前空間はクラスに埋め込まれているため、これは重要ではありません) )。

2)クラスの物理コピーが1つになるように、クラスファイルをリンクとしてプロジェクトに追加します。

3)dataContractSerializerをまだ持っていない場合は、WCF構成に追加します。

4)クライアント側で、サービスを右クリックし、[サービス参照の構成...]を選択します。表示されるダイアログで、Reuse types in all referenced assembliesがチェックされ、Reuse types in all referenced assembliesオプションが選択されていることを確認します。

5)これを機能させるための最も難しい部分は、コレクションです。

a) CollectionDataContract属性を使用してコレクションを装飾します。

b)このコレクションのエントリをreference.svcmapCollectionMappingsテーブルに追加します。reference.svcmapを見つけるには、プロジェクト内のすべてのファイルを表示してから、サービスを展開します。編集するには、ファイルをダブルクリックするだけです。シリアル化する特定のコレクションごとにここにエントリを追加し、List<>ベースのアイテムとDictionary<>ベースのアイテムを区別する必要があります。この手順を実行しないと、WCFはこれらのクラスを基になる汎用署名に自動的にシリアル化し、クラスを使用できなくなります。

このテーブルのエントリは次のようになります。

<CollectionMappings>
  <CollectionMapping TypeName="System.Collections.Generic.Dictionary`2" Category="Dictionary" />
  <CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" />
  <CollectionMapping TypeName="System.Collections.Specialized.StringCollection" Category="List" />
  <CollectionMapping TypeName="My.Namespace.MyDictionaryCollection" Category="Dictionary" />

これらのエントリを追加してファイルを保存すると、WCFクライアント側ジェネレーターは、使用している言語に応じて、reference.csまたはreference.vbファイルを再構築します。生成されたコードを見ると、参照が正しく構成されていないかどうかがわかります。そのコードにクラス定義が含まれている場合、WCFコードジェネレーターは何らかの理由でコピーしたクラスにマップできませんでした。

最後の注意:WCFコードジェネレーターがコードの生成に完全に失敗することがありますが、これは常にサービスの問題が原因です(通常、クラスが十分に一意でないか、何らかの理由で型をシリアル化できませんでした) 。

このタイプの問題をデバッグするために行う最も簡単な方法は、WCF診断ログを追加することです。これにより、エラーメッセージにドリルダウンできる特別なツール(名前を忘れる)で開くことができるファイルが生成されます。何が悪かったのかを正確に発見します。これにより、膨大な時間の作業を節約できました。このロギングを構成するには、<configuration>セクションの任意の場所でweb.configに以下を追加します。

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true">
        <listeners>
          <add name="traceListener"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData="c:\log\WcfTrace.svclog"  />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

これを追加してweb.configを保存したら、クライアントでサービス参照を更新してから、指定したログファイルをダブルクリックすると、ツールが開きます。

于 2013-01-06T18:38:28.433 に答える
4

これらの属性が必要になります。AutoMapper すべてのプロパティを手動で設定するのは面倒な場合があるため、作業を楽にするために、データ転送オブジェクトの配線を行うようなツールを使用できます。

とにかく、モデルへの変更がデータコントラクトに直接影響を与える必要がないように、モデルクラスをデータコントラクトから分離しておくことをお勧めします。

于 2013-01-06T18:33:42.133 に答える