6

Zauważyłem w samouczkach przechwytywania, że ​​można kierować metodą i przechwytywać ją. To znaczy.Przechwytywanie na poziomie metod z paramami

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

Dokumentacja/poradnik nie obejmuje, co robić w przypadku, że sposób starasz się przechwycić ma parametry tj jeśli ThrowsAnError akceptowane ciąg jako parametr.

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

W momencie wiązania nie mam dostępu do params, więc zastanawiałem się, czy podchodzę do tego w niewłaściwy sposób?

Edit

Working example

Odpowiedz

3

Myślę, że nieporozumienie, co się dzieje. Twój obiekt Foo zostanie zastąpiony dekoratorem, który zawiera przechwytywacz. Oto uproszczony przykład:

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

Innymi słowy, parametry, które są dostarczane, gdy rozwiązany Foo jest nazywany, zostanie przeniesiony na zdobionej instancji.

Jednak z przechwytywaniem wszystko to jest nieco bardziej pośrednie (i wolniejsze), ale koncepcja jest taka sama. Muszę przyznać, że nie jestem zaznajomiony z przechwytywaniem Ninject, ale prawdopodobnie istnieje metoda Proceed na obiekcie . Innymi słowy, należy zrobić tak:

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

Zakładam, że pierwszy argument metody InterceptReplace<T> nie jest delegatem, ale drzewa wyrażenie, takie jak Expression<Action<T>>. Ta metoda w rzeczywistości nie jest wywoływana, ale jest analizowana, aby dowiedzieć się, która metoda przechwycić. Innymi słowy, ponieważ ta metoda nigdy nie jest wywoływana, możesz po prostu podać dowolny argument. Sztuczka polega na tym, aby kompilator C# wiedział, której metody należy przeciążać (jeśli jest). Nie ma znaczenia, czy dostarczasz śmieci. Kiedy oba argumenty są typy referencyjne, to prawdopodobnie będzie działać:

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

widzę gdzie pochodzą, ale myślę, że PO będzie miało wiążącą tej metody jako problemowi, 'Kernel.InterceptReplace (foo => foo.ThrowsAnError(), ...); 'wymagałoby wprowadzenia tam argumentów, w przeciwnym razie nie skompiluje się, ponieważ ThrowsAnError wymaga poprawnie N argumentów, w twojej instancji będziesz musiał powiązać, tak jak ja * myślę *. 'Kernel.InterceptReplace (foo => foo.ThrowsAnError (jakośSatisfyParam1, jakośSatisfyParam2), ...);' Mogę się mylić. – Grofit

+1

Grofit jest poprawny, '' foo.ThrowsAnError() 'nadal będzie oczekiwał zapisu paramusterów –

+1

@MarkWalsh: Ahh, rozumiem. Zobacz moją aktualizację. – Steven

Powiązane problemy