Castle Windsor Interceptor not working with Method-Level attribute
Asked Answered
S

2

5

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

Skaw answered 15/1, 2014 at 21:11 Comment(0)
I
7

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
}
Inebriate answered 16/1, 2014 at 7:37 Comment(1)
Thanks - this is a good workaround. Hopefully there's a cleaner way to do this though without having to intercept all of the class' methods.Skaw
J
3

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.

Jilleen answered 16/1, 2014 at 3:34 Comment(2)
This makes me sad. I'm pretty new to AOP but it seems like method-level interceptors would be a nice feature to offer. Thanks for the help!Skaw
Just a note that with PostSharp, it's much easier to do what you're trying :)Jilleen

© 2022 - 2024 — McMap. All rights reserved.