6

Ho notato nei tutorial per l'intercettazione che puoi scegliere come target un metodo e intercettarlo. CioèNinject Interception a livello di metodo con parametri

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

La documentazione/esercitazione non riguarda cosa fare nel caso che il metodo che si sta cercando di intercettare ha parametri cioè se ThrowsAnError accettato una stringa come parametro.

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

Al momento della rilegatura non ho accesso ai params quindi mi chiedevo se sto andando su questo nel modo sbagliato?

Modifica

Working example

risposta

3

Penso che tu sia equivoco che cosa accade. L'oggetto Foo viene sostituito con un decoratore che contiene l'intercettore. Ecco un esempio semplicistico:

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); 
    } 
} 

In altre parole, sarà trasferita i parametri che vengono forniti quando il Foo risolto è chiamata, l'istanza decorato.

Con l'intercettazione, tuttavia, tutto questo è un po 'più indiretto (e più lento), ma il concetto è lo stesso. Devo ammettere che non ho familiarità con l'intercettazione di Ninject, ma probabilmente c'è un metodo Proceed sull'oggetto invocation. In altre parole, si dovrebbe fare qualcosa di simile:

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

Suppongo che il primo argomento del metodo InterceptReplace<T> non è un delegato, ma un albero di espressione, come ad esempio Expression<Action<T>>. Questo metodo, infatti, non viene chiamato, ma viene analizzato per scoprire quale metodo intercettare. In altre parole, poiché il metodo non viene mai chiamato, puoi semplicemente fornire qualsiasi argomento tu quale. Il trucco è lasciare che il compilatore C# sappia quale metodo utilizzare (se esiste). Non importa se fornisci spazzatura. Quando entrambi gli argomenti sono tipi di riferimento, questo sarà probabilmente funziona:

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

vedo dove si sono provenienti da, ma penso che il PO avrà un problema di legame a tale metodo come il 'Kernel.InterceptReplace (foo => foo.ThrowsAnError(), ...); 'richiederebbe l'inserimento di argomenti, altrimenti non verrà compilato come ThrowsAnError richiede N argomenti a destra, nella tua istanza dovresti associarlo così * penso *. 'Kernel.InterceptReplace (foo => foo.ThrowsAnError (somehowSatisfyParam1, somehowSatisfyParam2), ...);' Tuttavia, potrei sbagliarmi. – Grofit

+1

Grofit è corretto, il 'foo.ThrowsAnError()' si aspetta comunque che i parametri siano stipulati –

+1

@MarkWalsh: Ahh, capisco. Vedi il mio aggiornamento. – Steven