技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

基本的な Aspect 実装をしてみた

結局、RealProxy 経由する限り、オブジェクトが MarshalByRefObject になるのは避けれないし、Attribute 実装で new をフックするにも、ContextBoundObject でないと、Attribute インスタンスでフックできない。
とはいえ、これはこれで使ったほうが早いかと思ったので、簡易ライブラリ化してみた。

http://www.white-azalea.net/index.php/p/azaleaworks/downloads/

これの機能追加だけでもしばらく楽しそうね。ということで、以下に使い方。

namespace TestAspect
{
    class Program
    {
        static void Main(string[] args)
        {
            SampleTarget target = new SampleTarget();
            target.Hello("Azalea");
        }
    }
}

お次に、SampleTarget

namespace TestAspect
{
    [AzaleaWorks.Aspect.Aspect(typeof(TestLogger))]
    class SampleTarget : ContextBoundObject
    {
        internal void Hello(string p)
        {
            Console.WriteLine("Message : {0}!", p);
        }
    }
}

最後に TestLogger の実装。

namespace TestAspect
{
    class TestLogger : AzaleaWorks.Aspect.ProxyBase
    {
        public override IMessage
            InvokeMethod(IMethodCallMessage iMethodCallMessage)
        {
            Console.WriteLine("Called method : {0}", iMethodCallMessage.MethodName);
            IMessage result = base.InvokeMethod(iMethodCallMessage);
            Console.WriteLine("Exit   method : {0}", iMethodCallMessage.MethodName);
            return result;
        }
    }
}

InvokeConstructor メソッドも用意してあります。
適当に ProxyBase 継承したクラス作って、AspectAttribute に登録するだけ。
お察しの通り、インスタンス生成は Attribute でやってるから、引数なしのコンストラクタのみ対応。当然 Reflection でインスタンス生成してるし、キャッシュしてないから、インスタンスの大量生成をすると遅くなるかもね。

まずはインスタンスキャッシュと登録機構かなぁ?Aspectインスタンスを自前で作ってキャッシュする。で、使いまわす。既存のとは使い勝手違うから、別実装で用意かなぁ、、、、。
this ポインタ使うと補足できない、、、、RealProxy の限界かなぁ、、、、。
DynamicProxy 型だと事前にインターフェースを作って実装という制限が入るし、どうしたものか。