MixIn Interfaces Proxy
Seasar.DynamicProxyで2回インターセプターが実行される
Interfaceを実装している場合は、Interface毎にProxyを作成していたのですが、Interface毎のProxyを作るときに既に拡張されたクラスからProxyを作ろうとしていたためです。DynamicAopProxyAspectWeaverの問題ですね。
複数のインタフェースがMixinされたプロキシを作るのが目的なのであれば、DynamicProxyの機能が使えると思う。Castle.DynamicProxyのProxyGeneratorのCreateメソッドのバリエーションを利用して、
Type[] interfaces = 対象となる全てのインタフェースのMixin(配列) ProxyGenerator generator = new ProxyGenerator(); generator.CreateInterfaceProxy(interfaces, targetObject.GetType();
こんな風に、一発でMixinのプロキシが生成できますので、DynamicAopProxyクラスには、これに対応したインタフェースプロキシ専用のコンストラクタを用意して、
public DynamicAopProxy(Type interfaces, IAspect aspects, Hashtable parameters, object target)
{
this.target = target;
if (this.target == null) this.target = new object();
this.type = target.GetType();
this.aspects = aspects;
this.parameters = parameters;
this.generator = new ProxyGenerator();
this.enhancedType = this.generator.ProxyBuilder.CreateInterfaceProxy(interfaces, this.target.GetType());
isInterfaceProxy = true;
this.SetUpAspects();
}
これでを呼び出せば、一発で対象のインタフェース全てをMixinしたプロキシの型が生成できるのではないだろうか。このように拡張した型は、コンストラクタのパラメタが一つ多くなるので、プロキシインスタンスの生成では、
public object Create() { ArrayList args = new ArrayList(); args.Add(this); if (this.isInterfaceProxy && this.target != null) { args.Add(this.target.GetType()); } return Activator.CreateInstance(this.enhancedType, args.ToArray()); }
などと、ベタだがコンストラクタでセットしたisInterfaceProxyフィールドを判定して、コンストラクタの引数に、ターゲットの型をセットする必要がある。
と、こんな感じでできないだろうか。
公開したソースコードに関しては既に修正済み。
Seasar.Framework.Aop.DynamicProxy.DynamicAopProxy.cs
※自前のソースとの違いを出来るだけ減らしたいので、今回より.NET Framework 2.0専用としました。