Ilya Chumakov
Ilya Chumakov

Reputation: 25019

How to add an interceptor to a particular method using Ninject

To intercept a particular method with Ninject, I do this:

[MyInterceptor] void MyMethod()

or this:

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

I want to add all interceptors in a single place like (kernel config) and keep MyMethod free from any attributes. However, this Kernel.InterceptAround signature accepting Action instead IInterceptor looks weird! I would prefer full control of method execution.

Is it possible to add an interceptor for a particular method (not for a type at all!) without attributes, probably with Ninject extension? I mean a syntax like this:

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

Filter by method's name inside the interceptor is not a good option. Feel free to suggest another DI container.

Upvotes: 2

Views: 1942

Answers (1)

Yacoub Massad
Yacoub Massad

Reputation: 27861

I would prefer full control of method execution

While InterceptAround allows you only to specify what happens before and after execution, InterceptReplace can give you full control by allowing you to invoke IInvocation.Proceed manually (or not invoke it if you want).

Here is an example:

Create an interceptor like this:

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

        invocation.Proceed();

        //Do after
    }
}

And then you can use the InterceptReplace method like this:

var my_interceptor = new Interceptor();

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

You can create extension methods to help you get a different syntax that you like. Here is an example:

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

This allows you to simplify the syntax to be like this:

var my_interceptor = new Interceptor();

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

And here is another example for an extension method (based on Alexei Levenkov comment):

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

Which allows you to do:

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

Upvotes: 3

Related Questions