Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Castle Windsor Interceptor not working with Method-Level attribute

I have a Castle Interceptor that I'm trying to apply via attributes. It's working great when I apply my Interceptor attribute at class-level, but it's not working at all when I'm applying at method-level. What am I doing wrong? I don't want to intercept every method on a class, but instead flag certain methods with the [Interceptor] attribute. I've tried marking my methods as virtual, but it still doesn't work. Here's my code:

This works and all methods are intercepted:

[Interceptor(typeof(CacheInterceptor))]
public class Foo : IFoo
{
   public int SomeMethod() { }
}

This is NOT working (attribute is at method level):

public class Foo : IFoo
{
   [Interceptor(typeof(CacheInterceptor))]
   public int SomeMethod() { }
}

The installer:

public class CacheInterceptorInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<CacheInterceptor>().LifeStyle.Singleton);

        container.Register(Component
            .For<ICacheProvider>()
            .LifeStyle.Singleton
            .ImplementedBy<CacheProvider>());
    }
}

The interceptor:

public class CacheInterceptor : IInterceptor
{
    private readonly ICacheProvider _cacheProvider;

    public CacheInterceptor(ICacheProvider cacheProvider)
    {
        _cacheProvider = cacheProvider;
    }

    public void Intercept(IInvocation invocation)
    {
       // do interception stuff
    }
}

Thanks,

Andy

like image 967
Andy Avatar asked Jan 15 '14 21:01

Andy


2 Answers

You can use custom attribute to select methods to be intercepted:

[Interceptor(typeof(CacheInterceptor))]
public class Foo : IFoo
{
   [Cache]
   public int SomeMethod() { }
}

Then in Intercept method check, if the method has custom attribute:

if (invocation.MethodInvocationTarget.IsDefined(typeof(CacheAttribute))) {
  // do interception stuff
}
like image 56
Aleš Roubíček Avatar answered Sep 27 '22 22:09

Aleš Roubíček


Unfortunately, I don't think there's a way to use the Interceptor attribute just on a method. From http://docs.castleproject.org/Windsor.Interceptors.ashx:

The InterceptorAttribute is defined in a way that allows you to put it not only on classes, but on any other target where custom attribute is allowed, like interface or a method. However Windsor will ignore the attribute unless it's on component's implementation class. This permissive behavior was introduced to allow people to add support for other targets by building custom extensions.

(emphasis is mine)

I think something that might be useful in Castle is IProxyGenerationHook and/or IInterceptorSelector. Some documentation on this: http://docs.castleproject.org/Tools.Use-proxy-generation-hooks-and-interceptor-selectors-for-fine-grained-control.ashx

But, I don't see any way of using an IInterceptorSelector with the Interceptor attribute.

like image 23
Matthew Groves Avatar answered Sep 27 '22 22:09

Matthew Groves