2016-10-05 3 views
0

私は新しいプロジェクトを開始しており、SimpleInjectorインターセプト(https://simpleinjector.readthedocs.io/en/latest/InterceptionExtensions.html)を使用して、メソッドの入口/出口とロギングパラメータと戻り値などをトレースすることを考えています。過去にこのインターセプタを使用しました。よく働く。しかし私の以前のプロジェクトは、非同期/待たずでした。この新しいプロジェクトには、非同期/待機のすべてのメソッドがあり、私は不思議に思っていましたasync/aswaitコードでのSimpleInjectorインターセプト

  • このインターセプタは非同期/待機メソッドで動作しますか?
  • このインターセプタでは、非同期/待機メソッドでどのような変更を行う必要がありますか?

私はデコレータが傍受よりもはるかに良いパターンであることを理解していますが、トレースしたいインターフェイスごとにデコレータを書くことは、私がやりたいことではありません。

更新: 私の非同期/待機コードでこのインターセプタを試してみましたが、トレースコードが挿入されました。しかし、私はアプリケーションのいくつかの部分で奇妙な結果を得ていました。私は、傍受を無効にすると、それがうまく動作する理由と、傍受が有効になったときに、なぜ期待どおりに動作しないのかを詳しく知る機会はありませんでした。私のコードでは間違いかもしれません。

コードでこのインターセプト拡張をすでに使用している誰かが私に正しい方向を向けることができたらと思っていました。

+1

は '非同期/ため、このインターセプタ作業はメソッドを待ってます'、あなたがそれをしようとしたとき、それは動作しましたか? –

+1

"それは動作するのですか?"非同期呼び出しを処理するメソッドを明示的に記述すると、そうです。 – Steven

答えて

1

このインターセプタは、非同期/待機方式で動作しますか?

C#の非同期コードは、Taskの上に構文上の砂糖です。つまり、の後にの呼び出しで非同期メソッドを呼び出す必要がある場合は、Task(またはC#構文を使用)にContinueWithを呼び出す必要があります。インターセプタで非同期を考慮する場合、ラップされたオブジェクトの後にロジックを実行することはできません。

ラップされたメソッドがTaskを返すかどうかを明示的にチェックする必要があります。その場合は、ContinueWithを使用して 'after'コードをフックして非同期にする必要があります。

これは、私が傍受をデコレータを使用するよりも劣ると考えている多くの理由の1つです。デコレータは、コードをもっときれいにし、リフレクションの使用を控え、コンパイル時間のサポートを完全にし、パフォーマンスを向上させ、インターセプトライブラリに依存しないようにし、より多くのSOLIDアプリケーション設計を強制します。次のようにそれを考慮に非同期を取るときのドキュメントのMonitoringInterceptorが見えるだろう、と述べた

class MonitoringInterceptor : IInterceptor 
{ 
    private readonly ILogger logger; 

    public MonitoringInterceptor(ILogger logger) { 
     this.logger = logger; 
    } 

    public void Intercept(IInvocation invocation) { 
     var watch = Stopwatch.StartNew(); 

     // Calls the decorated instance. 
     invocation.Proceed(); 

     var task = invocation.ReturnValue as Task; 

     if (task != null) { 
      invocation.ReturnValue = LogElapsedAsync(task, invocation, watch); 
     } else { 
      LogElapsed(invocation, watch); 
     } 
    } 

    private async Task LogElapsedAsync(Task task, IInvocation i, Stopwatch w) { 
     await task; 
     LogElapsed(i, w); 
    } 

    private void LogElapsed(IInvocation invocation, Stopwatch watch) { 
     var decoratedType = invocation.InvocationTarget.GetType(); 

     this.logger.Log(string.Format("{0} executed in {1} ms.", 
      decoratedType.Name, watch.ElapsedMilliseconds)); 
    } 
} 
+0

例インターセプト拡張では、 'IInterceptor.Intercept'メソッドは' void'を返します。 'async/await'と一緒に使用したい場合、戻り値の型を' Task'に変更してそれに応じて変更する必要がありますか?または、[Async Programming:Unity Interceptionを使用した非同期メソッドのインターセプト](https://msdn.microsoft.com/en-us/magazine/dn574805.aspx)からコードを借用し、 'invocation.ReturnValue'を' .GetConcreateMethod()。ReturnType'は 'Task'ですか? – user2321864

+1

@ user2321864:更新を参照してください。 – Steven

関連する問題