web-dev-qa-db-ja.com

WCF ChannelFactoryとプロキシの生成

ChannelFactoryを使用して呼び出しを呼び出すことができるのに、どのような状況でWCFサービスからプロキシを生成したいのでしょうか?

この方法では、プロキシを生成する必要がなく、サーバーが更新されたときにプロキシを再生成する必要がありませんか?

ありがとう

81
TheWommies

WCFクライアントを作成するには、3つの基本的な方法があります。

  1. Visual Studioでプロキシを生成します。この自動により、WSDLを読み取ることでサービスに接続するコードが生成されます。何らかの理由でサービスが変更された場合は、再生成する必要があります。これの大きな利点は、セットアップが簡単なことです-VSにはウィザードがあり、すべて自動です。欠点は、VSに頼ってすべてのハードワークを実行しているため、コントロールを失うことです。

  2. 既知のインターフェイスでChannelFactoryを使用します。これは、サービス(サービスコントラクト)を記述するローカルインターフェイスを持つことに依存します。大きな利点は、変更をより簡単に管理できることです。変更を再コンパイルして修正する必要がありますが、コードを再生成せずに、新しいインターフェイスを参照します。一般に、これはサーバーとクライアントの両方を制御するときに使用されます。これは、両方を単体テスト用にはるかに簡単に模擬できるためです。ただし、REST ones- このTwitter API を見てください。

  3. 独自のプロキシを作成する-これは、特にRESTサービスの場合、HttpClientまたはWebClientを使用すると非常に簡単です。これにより、最もきめ細かい制御が可能になります。 、ただし、多くのサービスAPIが文字列に含まれているという犠牲を払って:たとえば、var content = new HttpClient().Get("http://yoursite.com/resource/id").Content;-APIの詳細が変更された場合、実行時までエラーは発生しません。

個人的に私はオプション1が好きではありませんでした-自動生成されたコードに依存することは面倒であり、あまりにも多くの制御を失います。さらに、多くの場合、シリアル化の問題が発生します。2つの同一のクラス(サーバーコードに1つ、自動生成に1つ)がありますが、それらは調整できますが、苦痛です。

オプション2は完璧でなければなりませんが、チャンネルは少し制限が厳しすぎます-例えば、それらは HTTPエラーの内容を完全に失います 。それは、サービスを記述するインターフェースを持つことで、コーディングと保守がはるかに簡単になるということです。

86
Keith

MetadataResolver.ResolveメソッドとともにChannelFactoryを使用します。クライアント構成は面倒なので、サーバーからServiceEndpointを取得します。

ChannelFactory(Of T)を使用する場合、Tはプロジェクト内の参照から取得できる元のコントラクトまたは生成されたコントラクトインスタンスのいずれかです。一部のプロジェクトでは、コントラクトdllへの参照を追加できなかったため、サービス参照からコードを生成しました。サービス参照を使用して非同期コントラクトを生成し、ChannelFactoryでそのコントラクトインターフェイスを使用することもできます。

ChannelFactoryを使用する主なポイントは、WCFクライアントの構成情報を取り除くことでした。以下のサンプルコードでは、構成なしでWCFクライアントを実現する方法を見ることができます。

Dim fixedAddress = "net.tcp://server/service.svc/mex"
Dim availableBindings = MetadataResolver.Resolve(GetType(ContractAssembly.IContractName), New EndpointAddress(fixedAddress))
factoryService = New ChannelFactory(Of ContractAssembly.IContractName)(availableBindings(0))
accesService = factoryService.CreateChannel()

私の最終プロジェクトでは、使用可能な場合、net.tcpまたはnet.pipeを使用するためにavailableBindingsがチェックされます。そのようにして、私は自分のニーズに最適なバインディングを使用できます。サーバーにメタデータエンドポイントが存在するという事実にのみ依存しています。

これが役立つことを願っています

ところで、これは.NET 3.5を使用して行われます。ただし、4.0でも機能します。

21

ChannelFactory<T>を使用するには、サービスとクライアント間でコントラクトアセンブリを共有する必要があります。これで問題なければ、ChannelFactory<T>で時間を節約できます。

11
Andrew Hare

プロキシは、Niceのような非同期関数を構築します。

9
Aaron Fischer

私の答えは Keith'sAndrew Hare's の回答の要約です。

サーバーを制御せず、Visual Studioまたはsvcutilを使用して、WSDL/URLのみでプロキシを生成する場合。 (svcutilの動作が改善されると、Visual Studioが失敗する場合があることに注意してください)。

サーバーとクライアントの両方を制御する場合、インターフェース/契約を共有し、ChannelFactoryを呼び出します。

7

時間の節約だけではありません。 WSDLで生成されたプロキシを使用すると、サービス参照の更新を忘れると、ソリューションが一貫性のない状態のままになる可能性があるため、危険です。すべてがコンパイルされますが、サービスコントラクトは壊れています。私は、可能な限りChannelFactoryを使用することを明確に提案します。あなたはあなたの人生をずっと楽にします。

代替案として、プロジェクトをビルドするたびにSVCUtilユーティリティを呼び出してプロキシを作成するビルド前スクリプトを作成することもできますが、とにかくChannelFactoryはより洗練されていてエレガントです。

2
Paolo Costa