如何使用Ninject将拦截器添加到特定方法

时间:2016-01-19 17:03:52

标签: c# dependency-injection ninject

要使用Ninject拦截特定方法,我这样做:

[MyInterceptor] void MyMethod()

或者这个:

Kernel.InterceptAround<IMyClass>(c => c.MyMethod(), inv => { ... }, inv => { ... });

我想在一个地方添加所有拦截器,如(内核配置),并保持MyMethod不受任何属性的影响。但是,此Kernel.InterceptAround签名接受Action代替IInterceptor看起来很奇怪!我更希望完全控制方法执行。

是否可以在没有属性的情况下为特定方法(根本不是类型!)添加拦截器,可能使用Ninject扩展?我的意思是这样的语法:

Kernel.Intercept<IMyClass>(c => c.MyMethod()).With<MyInterceptor>();

在拦截器内按方法名称过滤不是一个好选择。随意建议另一个DI容器。

1 个答案:

答案 0 :(得分:3)

  

我更希望完全控制方法执行

虽然InterceptAround只允许您指定执行前后发生的事情,InterceptReplace可以让您完全控制,允许您手动调用IInvocation.Proceed(或者如果您需要,则不会调用它) )。

以下是一个例子:

像这样创建一个拦截器:

public class Interceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        //Do before

        invocation.Proceed();

        //Do after
    }
}

然后您可以像这样使用InterceptReplace方法:

var my_interceptor = new Interceptor();

Kernel.InterceptReplace<IMyClass>(
    c => c.MyMethod(),
    inv => my_interceptor.Intercept(inv));

您可以创建扩展方法,以帮助您获得您喜欢的不同语法。这是一个例子:

public static class MyExtentionMethods
{
    public static void UseInterceptorFor<T>(
        this IKernel kernel,
        Expression<Action<T>> methodExpr,
        IInterceptor interceptor)
    {
        kernel.InterceptReplace<T>(methodExpr, inv => interceptor.Intercept(inv));
    }
}

这允许您将语法简化为:

var my_interceptor = new Interceptor();

Kernel.UseInterceptorFor<IMyClass>(
    c => c.MyMethod(),
    my_interceptor);

以下是扩展方法的另一个例子(基于Alexei Levenkov评论):

public static class MyExtentionMethods
{
    public static void UseInterceptorFor<TObject,TInterceptor>(
        this IKernel kernel,
        Expression<Action<TObject>> methodExpr)
        where TInterceptor : IInterceptor
    {
        var interceptor = kernel.Get<TInterceptor>();

        kernel.InterceptReplace<TObject>(methodExpr, inv => interceptor.Intercept(inv));
    }
}

允许您这样做:

Kernel.UseInterceptorFor<IMyClass,Interceptor>(c => c.MyMethod());