[解決済み】WCFクライアント `using` ブロックの問題に対する最良の回避策は何ですか?
質問
WCFサービスクライアントのインスタンスを
using
を実装したリソースを利用するための標準的な方法だからです。
IDisposable
:
using (var client = new SomeWCFServiceClient())
{
//Do something with the client
}
でも述べたように
このMSDN記事
でWCFクライアントをラップすることです。
using
ブロックは、クライアントを障害状態 (タイムアウトや通信の問題など) にするエラーを隠蔽することができます。簡単に説明すると
Dispose()
が呼び出されると、クライアントの
Close()
メソッドが起動しますが、faulted 状態であるため、エラーを投げます。このとき、元の例外は2番目の例外によって隠されます。これは良くないことです。
MSDN の記事で提案されている回避策は、完全に
using
ブロックの代わりに、クライアントをインスタンス化して、次のように使用します。
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
と比較すると
using
ブロックは、醜いと思います。それに、クライアントが必要になるたびに、たくさんのコードを書かなければなりません。
幸いなことに、IServiceOrientedブログ(今は亡き)にあるような、他の回避策をいくつか見つけました。まず最初に
public delegate void UseServiceDelegate<T>(T proxy);
public static class Service<T>
{
public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>("");
public static void Use(UseServiceDelegate<T> codeBlock)
{
IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel();
bool success = false;
try
{
codeBlock((T)proxy);
proxy.Close();
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
}
とすると、可能になります。
Service<IOrderService>.Use(orderService =>
{
orderService.PlaceOrder(request);
});
それも悪くはないのですが、表現力、わかりやすさでは
using
ブロックを使用します。
私が現在試している回避策は、最初に読んだのは
blog.davidbarret.net
. 基本的には、クライアントの
Dispose()
メソッドを使用します。のようなものです。
public partial class SomeWCFServiceClient : IDisposable
{
void IDisposable.Dispose()
{
if (this.State == CommunicationState.Faulted)
{
this.Abort();
}
else
{
this.Close();
}
}
}
これによって
using
を再びブロックすることで、faulted stateの例外を隠してしまう危険性がありません。
では、これらの回避策を使って、他に気をつけなければならないことはあるのでしょうか?どなたか、もっと良い方法を思いついた方はいらっしゃいますか?
解決方法は?
実は、私は ブログ 参照 ルークからの回答 ) と思います。 これ は、私の IDisposable ラッパーよりも優れています。典型的なコードです。
Service<IOrderService>.Use(orderService=>
{
orderService.PlaceOrder(request);
});
(コメントごとに編集)
から
Use
は void を返すので、戻り値を処理する最も簡単な方法は、キャプチャした変数を使うことです。
int newOrderId = 0; // need a value for definite assignment
Service<IOrderService>.Use(orderService=>
{
newOrderId = orderService.PlaceOrder(request);
});
Console.WriteLine(newOrderId); // should be updated
関連
-
[解決済み] 'SubSonic.Schema .DatabaseColumn' 型のオブジェクトをシリアライズする際に、循環参照が検出されました。
-
[解決済み】「namespace x already contains a definition for x」エラーの修正方法は?VS2010にコンバートした後に発生しました。
-
[解決済み】Unity3DでOnTriggerEnterが動作しない件
-
[解決済み] [Solved] アセンブリ System.Web.Extensions dll はどこにありますか?
-
[解決済み】Moqを使用してメソッド呼び出しを検証する
-
[解決済み】画像のペイントにTextureBrushを使用する方法
-
[解決済み】ユーザー設定値を別のユーザー設定値で設定する
-
[解決済み] C#の正しいバージョン番号を教えてください。
-
[解決済み] C#のオートプロパティに初期値を与える最良の方法は何ですか?
-
[解決済み】C#のyieldキーワードは何に使われるのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】ここで「要求URIに一致するHTTPリソースが見つかりませんでした」となるのはなぜですか?
-
[解決済み】C#はJavaのcharAt()と同等?)
-
[解決済み】ソケットのアドレス(プロトコル/ネットワークアドレス/ポート)は、通常1つしか使用できない?
-
[解決済み】「namespace x already contains a definition for x」エラーの修正方法は?VS2010にコンバートした後に発生しました。
-
[解決済み】バックスラッシュを含むパス文字列のエスケープシーケンスが認識されない件
-
[解決済み】非静的メソッドはターゲットを必要とする
-
[解決済み】C# - パスに不正な文字がある場合
-
[解決済み】「...は'型'であり、与えられたコンテキストでは有効ではありません」を解決するにはどうすればよいですか?(C#)
-
[解決済み】「namespace」なのに「type」のように使われる。
-
[解決済み】ファイルやアセンブリ、またはその依存関係の1つをロードできませんでした。