Interceptors with Castle.Windsor

While registering a dependency I can tell Castle that I want to set an interceptor for its methods. Before each dependency’s method is invoked the interceptor will be called, with the opportunity to proceed with the invocation, stop it, or execute other operation before its execution. Interceptors are very useful with legacy code, that we prefer not to touch, to append additional behaviors to the methods. Here is an example with different ways to set an interceptor:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(
 
        //Here I'm setting the interceptors for the IRepository dependency.
        //I'm referring the interceptors to use by telling Castle their name.
        //With "Anywhere" I'm telling that all the interceptor must trigger
        Component.For<IInterceptor>().ImplementedBy<RepositoryInterceptor>()
            .Named("RepositoryInterceptor"),
        Component.For<IRepository>().ImplementedBy<Repository>()
            .Interceptors(InterceptorReference.ForKey("RepositoryInterceptor"))
            .Anywhere,
 
        //Here I'm telling Castle which interceptor to use by its type. I can
        //create sub-interfaces of IInterceptor to group different interceptors
        Component.For<IInterceptor>().ImplementedBy<RepositoryInterceptor>(),
        Component.For<IRepository>().ImplementedBy<Repository>()
            .Interceptors(InterceptorReference.ForType<IInterceptor>()).Anywhere,
 
        //This is another way to refer interceptors by type
        Component.For<IInterceptor>().ImplementedBy<RepositoryInterceptor>(),
        Component.For<IRepository>().ImplementedBy<Repository>()
            .Interceptors<IInterceptor>(),
 
        //Here I'm using a selector to filter which interceptor use for each
        //method of the target dependency. Is useful when i want an interceptor
        //to be called only for some particular methods
        Component.For<IInterceptor>().ImplementedBy<RepositoryInterceptor>(),
        Component.For<IRepository>().ImplementedBy<Repository>()
            .Interceptors(InterceptorReference.ForType<IInterceptor>())
            .SelectedWith(new InterceptorSelector()).Anywhere,
 
        Component.For<IService>().ImplementedBy<Service>());
}

Here is our interceptor:

public class RepositoryInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Debug.Print("The Repository {0} method has been called with arguments {1}",
            invocation.Method.Name, invocation.Arguments.FirstOrDefault());
        invocation.Proceed();
    }
}

Here is our selector:

public class InterceptorSelector : IInterceptorSelector
{
    public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors)
    {
        if (type == typeof(Repository))
            if (method.Name == "GetList")
            {
                return interceptors.Where(i => i.GetType() == typeof(RepositoryInterceptor)).ToArray();
            }
        return null;
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s