7

インターセプトのチュートリアルで、メソッドをターゲットにしてインターセプトできることに気づきました。つまり

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

バインド時にパラメータにアクセスできないので、これを間違った方法で行っているのではないかと思っていました。

編集

実例

4

1 に答える 1

4

あなたは何が起こるか誤解していると思います。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インターセプトに精通していないことを認めなければなりませんが、おそらくオブジェクトにはProceedメソッドがありinvocationます。つまり、次のようなことを行う必要があります。

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

アップデート

InterceptReplace<T>メソッドの最初の引数はデリゲートではなく、などの式ツリーであると想定していExpression<Action<T>>ます。このメソッドは実際には呼び出されませんが、インターセプトするメソッドを見つけるために分析されます。つまり、メソッドが呼び出されることはないため、任意の引数を指定するだけで済みます。秘訣は、使用するメソッドのオーバーロード(存在する場合)をC#コンパイラに知らせることです。ごみを出すかどうかは関係ありません。両方の引数が参照型の場合、これはおそらく機能します。

Kernel.InterceptReplace<Foo>(foo => foo.ThrowsAnError(null, null),
于 2012-11-06T13:25:35.563 に答える