IL EmissionによるAOP (1)
以前に日記で言及したことがある.NETにおけるDIコンテナ上のAOPの実現ですが拙作のフレームワークはS2.NETと同様にRealProxyを使用した"Proxy"方式のAOPを実装しています。
この手法はRealProxyの派生型はその対象となった型の全てのメソッドの実行機会を補足(インターセプト)できる、という振る舞いを利用しており手軽にAOPを実現できる良い方法なのですが残念ながら以下の制限が存在します。
1.AOPが適用できるのはinterface実装クラスかMarshalByRefクラスを拡張したクラスだけ
2.AOPが適用できるのはコンテナを介して取得した透過プロキシだけ
1.は現在のプログラミングの基本概念がクラスからインタフェースに移ってきていることからしてもAOPを適用する自由度が下がるだけですが2.は結構致命的です。
例えば以下のようなクラスの全てのメソッドを対象にしたAOPのアドバイスを適用しているとします。
public class HogeImpl : IHoge { private IHogeFriend friend; public HogeImpl(IHogeFriend friend) : base() { this.friend= friend; this.friend.SetHoge(this); } }設定ファイルはこんな感じでTrace用のインターセプタをアドバイスに適用したとしますTraceInterceptor
DIコンテナを介して取得したIHogeインタフェースは透過プロキシなのでAOPが適用されますが
IHoge hoge = DIContainer.Create().GetComponent(typeof(IHoge));
HogeImplコンストラクタ内で呼ばれているthis.friend.SetHogeメソッドの引数に使用されているthisキーワードで参照されるのは透過プロキシではなくHogeImpl自身ですので呼ばれた先ではAOPは無効になってしまいます。
this.friend.SetHoge(this); <-- thisは透過プロキシでは無い!
この制限があるばかりに最初にコンテナから取得した参照を長々と使いまわさなくてはならないのがどうしても我慢できないのでいろいろと解決策を模索していた訳です。
ごく最近になって制限付きながらやっと解決することができそうなので次のエントリから書いていこうと思います。