私が達成しようとしているのは、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);
}
}