2016-10-05 40 views
0

我開始一個新項目,並且正在考慮使用SimpleInjector攔截(https://simpleinjector.readthedocs.io/en/latest/InterceptionExtensions.html)來跟蹤方法進入/退出以及記錄參數和返回值等。我過去曾使用過這個攔截器,它效果很好。但我以前的項目不是異步/等待。這個新項目有很多方法,都是異步/等待,我想知道異步/等待代碼中的SimpleInjector攔截

  • 這個攔截器會爲async/await方法工作嗎?
  • 這個攔截器需要做什麼修改才能使它適用於異步/等待方法?

我明白,裝飾比攔截一個更好的模式,但寫的每一個界面,我想跟蹤一個裝飾是不是我很期待做的事情。

更新: 我試過這個攔截器在我的異步/等待代碼,它注入了我的跟蹤代碼。但是,在我的應用程序的某些部分,我收到了奇怪的結果。我沒有機會深入瞭解爲什麼禁用攔截會使其正常工作,並且爲什麼當啓用攔截時不能按預期工作。這可能是我的代碼有問題。

我希望如果有人已經在他們的代碼中使用了這種截取擴展,就能夠指引我朝着正確的方向發展。

+1

'會爲異步這個攔截工作/ await方法'難道它,當你嘗試過工作嗎? –

+1

「它會工作嗎?」如果你明確地寫你的方法來處理異步調用,是的。 – Steven

回答

1

這個攔截器是否可以用於異步/等待方法?

C#中的異步代碼是在Task之上的語法糖。這意味着如果您的代碼需要執行之後的任何有用調用異步方法,您將在返回的Task(或使用C#語法)上調用ContinueWith。如果在攔截器中考慮到異步,您將無法在包裝對象之後執行邏輯。

因此,要做到這一點,你必須明確檢查包裝的方法是否返回Task,如果是這種情況,你應該通過使用ContinueWith來鉤住你的'後'代碼來做異步。

這是我認爲攔截不如使用裝飾器的原因之一。裝飾器允許你的代碼更加乾淨,避免使用反射,提供完整的編譯時支持,提供更好的性能,避免依賴截取庫,並迫使你進入更加固定的應用程序設計。

那說,在文檔的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'並相應地進行更改?或者,我應該借用[異步編程:使用統一攔截攔截異步方法](https://msdn.microsoft.com/zh-cn/magazine/dn574805.aspx)中的代碼,並在調用時包裝「invocation.ReturnValue」 .GetConcreateMethod()。ReturnType'是'Task'? – user2321864

+1

@ user2321864:查看更新。 – Steven