RealProxyの限界
以前、日記でRealProxyをAOPのプロキシとして使う実装について言及してきましたが私が考えているシステムとフレームワーク上では以下の不都合が発生しており限界を感じています。
AOPのプロキシはRealProxyの派生クラスとして書きますが対象となる型のメソッドをインターセプトしてアスペクトのアドバイスを実行するためには対象のインスタンス自体をセットしなくてはなりません。
public AopProxy(Type type, object target, IAspect[] aspects) : base(type) { this.type = type; this.target = target; this.aspects = aspects; }
インスタンスをセットするということは既に生成は完了しているのですから生成する際に使用されたコンストラクタメソッドをインターセプトする事ができません。(というか私がその方法をまだ知らないだけかもれしません..)
これはAOPと共にDIContainerを使い、依存性注入の方法としてコンストラクタが起動された後に値を注入するセッターインジェクション又はプロパティインジェクションを扱う際には問題にはなりませんがコンストラクタインジェクションにおいては問題となります(アスペクトのアドバイスが実行されない)
- 自身の参照(this)をプロキシへの参照として外部に持ち出せない
最初の問題点に通ずる事ですが、以下のコンストラクタのようにメソッド内部で扱う自身の参照は特別な実装を施さない限りプロキシへの参照では無い
public ContributeActionTemplate(Contributer contributer) :this() { this.contributer= contributer; //contributer.BindAttributeメソッドにセットされるthisはプロキシでは無い this.contributer.BindAttribute(this); }
(※そもそもこのような参照を扱うことが正しいかどうかはここでは言及しません)
これらの不都合を回避するための方策ですが今のところ
1. プロキシのアクセサを用意して生成時には必ずプロキシをセットする
2. ContextBoundObjectとContextAttributeの組み合わせを使用する
3. TypeBuilderとILのEmitを組み合わせた動的な型の拡張を実装する
これらが考えられる訳ですが1.はAOPを適用したいケースでは特定のインタフェースに縛られることになるし、2.と3.、特に3.はかなり面倒だし柔軟性が下がるのは避けられないような気がします。
う〜ん、どうしようかなぁ。