AOP with Castle Windsor

1k Views Asked by At

What I'm trying to achieve is AOP via attributes using Castle Windsor interceptors. I've had some success but having trouble with the aspects at the class level vs. the method level.

  • If I use class level attributes only, all methods will be intercepted.
  • If I use method level attributes only, those methods will be intercepted.
  • If I add a class level attribute, and a method level attribute, both interceptions will happen on methods that were attributed, but the ones that were not will not be intercepted.

So given this component:

public interface IMyComponent
{
    void ShouldBeInterceptedByStopWatch_AND_ExceptionLogger();
    void ShouldBeInterceptedByExceptionLogger();
}

[LogExceptionAspect]
public class MyComponent : IMyComponent
{
    [StopwatchAspect]
    public void ShouldBeInterceptedByStopWatch_AND_ExceptionLogger()
    {
        for (var i = 0; i < 2; i++) Thread.Sleep(1000);
    }

    public void ShouldBeInterceptedByExceptionLogger()
    {
        throw new NotImplementedException();
    }
}

I would expect the logger aspect to intercept ShouldBeInterceptedByExceptionLogger() but its not happening unless I remove the stopwatch aspect from the other method, or remove the logger aspect from the class and add it to the ShouldBeInterceptedByExceptionLogger(). BUT the ShouldBeInterceptedByStopWatch_AND_ExceptionLogger() is intercepted by both.

The entire sample application can be found at - https://bitbucket.org/jayala/juggernet-aop

basically what its doing is using a facility to register a IContributeComponentModelConstruction that will add an interceptor if it finds an aspect at class level, or add an interceptor + method hooks if it finds aspects at method level.

This is how I bootstrap the container:

        var container = new WindsorContainer()
            .AddFacility<LogExceptionAspectFacility>()
            .AddFacility<StopwatchAspectFacility>()
            .Register(Component
                .For<IMyComponent>()
                .ImplementedBy<MyComponent>()
                .LifeStyle.Transient);

What the facilities are doing is registering an interceptor and a model contributor like this

public abstract class BaseAspectFacility<TAspectAttribute, TAspectInterceptor> : AbstractFacility
    where TAspectAttribute : Attribute
    where TAspectInterceptor : IInterceptor
{
    protected override void Init()
    {
        var interceptorName = Guid.NewGuid().ToString();
        Kernel.Register(Component.For<IInterceptor>()
                                 .Named(interceptorName)
                                 .ImplementedBy<TAspectInterceptor>()
                                 .LifeStyle.Singleton);
        var contributor = new ContributeAspectToModel<TAspectAttribute>(interceptorName);
        Kernel.ComponentModelBuilder.AddContributor(contributor);
    }
}
0

There are 0 best solutions below