DynamicAopProxyをs2dotnetに組み込む方法

このシリーズのエントリの最後は、id:sugimotokazuyaさんへのコメントに書いた通り、一連の実験で作ったCastle.DynamicProxyを利用したAopProxyである"DynamicAopProxy"をs2dotnetに組み込む方法を書いておこうと思う。

  • Castle.DynamicProxyの参照

これは特に説明する必要は無いだろう。対象のインストールパッケージをダウンロードするか、ソースコードリポジトリに接続して最新のソースコードをチェックアウトしてVisual Studioのプロジェクトを構成するだけでよいはずだ。あとはCastleプロジェクトに感謝しつつ、使うだけ。注意すべきなのは.NET Framework 2.0でビルドする場合。安定化版のバイナリ又はソースコードだとGenericsを使用した型をDynamicProxyで拡張した場合にメソッドの実行に失敗するので、必ず最新版(Change.txtによるとVersion 1.4.8)のリポジトリを使用することだ。(これで、半日潰した)

最新SVN -> http://svn.castleproject.org/svn/castle/trunk/Tools/DynamicProxy/
(※dotnet2コンパイルシンボルあり。.NET Framework 2.0用のプロジェクトは、このシンボルが有効になっているので注意)

  • DynamicAopProxyクラスを用意する

正確には、以下の二つのクラスを用意した。

DynamicAopProxy.cs(AopProxyをおきかえる、DynamicProxyを利用したプロキシクラス)
DynamicProxyMethodInvocation.cs(DynamicAopProxy用のInvocatorクラス)

ソースコードを書くと長くなるので、短期限定で、リンクを張った。そちらで見ていただきたい。

  • アスペクトをウィーブする際のコードを書き換える

s2Dotnetの場合、拡張された型のインスタンスを生成するコードはAopProxyUtilに局所化されているので、AopProxyを生成している部分を修正すればよいが、ユーザが自分の好みで、従来からあるRealProxyベースのプロキシと、DynamicProxyベースのプロキシを自由に選べるようにするのが良いと思う。プロキシ自体をコンポーネントとしてDIコンテナに登録する、等の方法が考えられるが、ここでは、コンパイル条件でプロキシを使い分けるサンプルを書いてみよう。

public static void WeaveAspect(ref object target, IComponentDef componentDef)
{
    if (componentDef.AspectDefSize == 0) return;
    Hashtable parameters = new Hashtable();
    parameters[ContainerConstants.COMPONENT_DEF_NAME] = componentDef;
#if DYNAMICPROXY
    DynamicAopProxy aopProxy = new DynamicAopProxy(componentDef.ComponentType,   GetAspects(componentDef), parameters, target);
    target = aopProxy.Create();
    componentDef.AddProxy(componentDef.ComponentType, target);
#else
    Type[] interfaces = componentDef.ComponentType.GetInterfaces();
    if (componentDef.ComponentType.IsMarshalByRef)
    {
        AopProxy aopProxy = new AopProxy(componentDef.ComponentType, GetAspects(componentDef), parameters, target);
        componentDef.AddProxy(componentDef.ComponentType, aopProxy.Create());
    }
〜略


必要な作業は以上だ。s2dotnetを知っている開発者であれば組み込みは簡単だと思うので、是非いろいろと試して、私がテストできなかった新たな活用方法や、問題や制限を報告してくれるとありがたい。特に、私はスマートクライアント(リッチクライアント)のインフラとしてDIコンテナを利用しているため、WindowsForms以外、ASP.NETADO.NETトランザクション周りは全くテストしていない。

また、私は意に介していないが、拡張した型で懸念されるもうひとつの問題は.NET独自のコードセキュリティの問題だと思う。拡張した型は厳密な名前付けがされず、署名も施されない。従ってコードセキュリティを破るか、又は無効にしてしまう可能性があるが、その点についてもまだ全くテストをしていないことを付け加えておく。

追記 (4/18 09:00 ソースコードを物置に置いてリンクを張った。)
追記 (4/18 12:00 DynamicAopProxy.csにバグがあったので修正)