私は DRY コーディングの大ファンで、定型コードはできるだけ避けたいと思っています。したがって、すべての WCF チャネル faff を、WCF チャネルのライフサイクルを処理する AOP クラスにリファクタリングしました。
また、私は async-await の大ファンでもあり、特に WCF では、通常はスリープ状態で応答を待機しているスレッドを理論的に解放できるためです。
そこで、fluentAOP lib にインターセプターを作成しました
private static object InvokeOnChannel(IMethodInvocation methodInvocation)
{
var proxy = _factory.CreateChannel();
var channel = (IChannel) proxy;
try
{
channel.Open();
var ret = methodInvocation.Method.Invoke(proxy, methodInvocation.Arguments);
channel.Close();
return ret;
}
catch (FaultException ex)
{
if (ex.InnerException != null)
throw ex.InnerException;
throw;
}
catch(Exception)
{
channel.Abort();
throw;
}
}
ただし、解決策について少し考えてみると、フォームの WCF コントラクトの場合、
[ServiceContract]
public interface IFoo
{
[OperationContract]
Task<int> GetInt();
}
GetInt は予期しない結果をもたらします。まず、catch FaultException は何もしません。次に、リクエストが返される前にチャネルを閉じます。戻り値の型が Task の場合、理論的には別のコード パスに切り替えることができます。しかし、Task<> の結果を待ってから awaitable を返す方法がわかりません。
もちろん、これは特に困難です。なぜなら、ランタイム AOP を使用すると、戻り値の型のジェネリックを使用できるアクセス権がないからです (リフレクションの全体がなければ)。
この関数を awaitable として実装する方法はありますか?完了時にチャネルを閉じ、呼び出しスレッドへの例外をキャッチ/マーシャリングしますか?