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