我想要实现的是使用 Castle Windsor 拦截器通过属性实现的 AOP。我取得了一些成功,但在类级别与方法级别的方面存在问题。
- 如果我只使用类级别的属性,所有的方法都会被拦截。
- 如果我只使用方法级别的属性,这些方法将被拦截。
- 如果我添加一个类级别的属性和一个方法级别的属性,这两种拦截都会发生在被赋予属性的方法上,但那些没有被赋予属性的方法不会被拦截。
所以给定这个组件:
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();
}
}
我希望记录器方面能够拦截ShouldBeInterceptedByExceptionLogger()
,但除非我从其他方法中删除秒表方面,或者从类中删除记录器方面并将其添加到ShouldBeInterceptedByExceptionLogger()
. 但是ShouldBeInterceptedByStopWatch_AND_ExceptionLogger()
两者都拦截了。
整个示例应用程序可以在 - https://bitbucket.org/jayala/juggernet-aop找到
基本上它所做的是使用一个工具来注册一个IContributeComponentModelConstruction
,如果它在类级别找到一个方面,它将添加一个拦截器,或者如果它在方法级别找到一个方面,则添加一个拦截器+方法挂钩。
这就是我引导容器的方式:
var container = new WindsorContainer()
.AddFacility<LogExceptionAspectFacility>()
.AddFacility<StopwatchAspectFacility>()
.Register(Component
.For<IMyComponent>()
.ImplementedBy<MyComponent>()
.LifeStyle.Transient);
这些设施正在做的是注册一个拦截器和一个像这样的模型贡献者
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);
}
}