6

我在攔截教程中已經注意到你可以定位一個方法並攔截它。即Ninject帶參數的方法級攔截

Kernel.Bind<Foo>().ToSelf(); 
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(), invocation => {}); 

文檔/教程並沒有什麼的情況下做到這一點你試圖攔截該方法具有參數即如果 ThrowsAnError接受一個字符串作爲參數。

Kernel.Bind<Foo>().ToSelf(); 
Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(**param goes here**), invocation => {}); 

在結合我沒有訪問PARAMS,所以我在想,我是否要對這個錯誤的方式的時候?

編輯

Working example

回答

3

我想你是誤會發生了什麼。您的Foo對象被包含攔截器的裝飾器替換。下面是一個簡單的例子:

public class FooDecorator : Foo 
{ 
    private readonly Foo decorated; 

    public FooDecorator(Foo foo) { this.decorated = foo; } 

    public void ThrowsAnError(object param1, int param2) 
    { 
     // calls the decorated instance with supplied parameters 
     this.decorated.ThrowsAnError(param1, param2); 
    } 
} 

換句話說,當解析的Foo被調用時提供的參數將被傳遞給裝飾實例。然而,儘管有攔截,但這是間接(更慢)的一點,但概念是一樣的。我必須承認我不熟悉Ninject攔截,但在invocation對象上可能有Proceed方法。換句話說,你應該做這樣的事情:

Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(), 
    invocation => 
    { 
     try 
     { 
      // calls the decorated instance with supplied parameters 
      invocation.Proceed(); 
     } 
     catch (Exception ex) 
     { 
      Kernel.Get<ILogger>().Log(ex); 
     } 
    }); 

UPDATE

我假設InterceptReplace<T>方法的第一個參數是不是代表,而是一個表達式樹,如Expression<Action<T>>。這個方法實際上並沒有被調用,但是它被分析以找出要攔截的方法。換句話說,由於該方法從未被調用過,所以你可以提供任何你自己的參數。訣竅是讓C#編譯器知道使用哪種方法重載(如果有的話)。你提供垃圾無關緊要。當兩個參數都是引用類型,這可能會工作:

Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(null, null), 
+1

我看你是從哪裏來的,但我覺得OP將有一個問題,因爲綁定到方法'Kernel.InterceptReplace (富=> foo.ThrowsAnError(),...);'會需要在那裏輸入參數,否則它不會編譯,因爲ThrowsAnError需要N個參數,在你的實例中,你將不得不像這樣綁定。 'Kernel.InterceptReplace (foo => foo.ThrowsAnError(somehowSatisfyParam1,somehowSatisfyParam2),...);'雖然我可能是錯的。 – Grofit

+1

Grofit是正確的,'foo.ThrowsAnError()'仍然需要params來規定 –

+1

@MarkWalsh:啊,我明白了。查看我的更新。 – Steven