DynamicProxy実験1
.NETの世界でAOPと言えばCastle.DynamicProxyが定番だと思いますが(・∀・)
NHibernateとかiBatis.NETなんかで使われているやつです。
#AOPでちょっと遊ぶ分にはContextBoundObjectの実装という話もありますが
ちなみにCastleプロジェクトを知ったのは、全て遠き理想郷…Apache Avalonプロジェクト解散のニュースを見たときです( ´д)
C#にもIoCフレームワーク/コンテナがあったんだな〜っと。
で、Castle.DynamicProxyの使い方はこんな感じになります。
// インタフェース public interface IMyInterface { int Hoge(int x, int y); } // 実装 public class MyInterfaceImpl : IMyInterface { public int Hoge(int x, int y) { return x + y; } } // インターセプター public class MyInterceptor : IInterceptor { public object Intercept(IInvocation invocation, params object[] args) { // 前処理 object ret = invocation.Proceed( args ); // 後処理 return ret; } } // 使用方法 ProxyGenerator generator = new ProxyGenerator(); IMyInterface proxy = generator.CreateProxy( typeof( IMyInterface ), new MyInterceptor(), new MyInterfaceImpl() ) as IMyInterface; int ret = inter.DoSomething( 1, 2 );
ProxyGenerator.CreateProxy()によりIMyInterfaceを実装したproxyが返されます。
proxyのメソッド呼び出し時にはMyInterceptorが適用され、Interceptor内のIInvocation.Proceed()によりtarget(MyInterfaceImpl)の処理が実行されます。
targetには通常だとIMyInterfaceの実装クラスを指定しますが。
Interceptorによってはtargetがいらないケースもあるので、試しにtargetにnullを指定してみたらそれはAssertionに引っかかりました(´・ω・`)
targetのいらないInterceptorってどういうものがあるかというと、interfaceをメタ情報として実際の処理を構築するフレームワークとかです。
ORMフレームワークの中には、メソッド名やメソッドシグネチャから定型処理を生成するものもあったりしますが、そういうやつです。
メタ情報を与えて定型処理を行うだけであれば、別にinterfaceでAOPする必要はありませんが。
あえてinterfaceをメタ情報に使う事のメリットは、interfaceの使用者があたかもそういうメソッドの実装があるかのように処理を呼び出せることでしょうか。
で、実際の処理はメタ情報をもとに別のところでやるので、IInvocation.Proceed()の必要はなく、targetも必要はありません。
ProxyGenerator.CreateProxy()の場合、targetには適当なオブジェクト(new object()とか)を入れておけばとりあえず動くようですが、それがどこまで合法なのかはちゃんとソースをチェックしてないので分かりません(´ω`)