新・プロクシを使ってAOP(もう飽きた編)

MethodInvocationのネスト対応。
というか、S2AOPからパクったw
ネスト(再回帰)させて伝搬させていけばいいかなと検討をつけてはいたんだけどやり方がぱっと思いつかなくて。
公開されてるソースをみたら、思いの外単純なことだった。
なんか難しく考えてたぽい。
こういうのをぱっと思い浮かぶようになりたいもんだわ。
以下、メモ程度に抜粋。
プロクシクラス。
属性(適用するInterceptor)の一覧を取得して、その先頭から実行すると。

public override IMessage Invoke(IMessage msg)
{
    IMethodCallMessage callMsg = (IMethodCallMessage)msg;
    MethodBase method = callMsg.MethodBase;

    List<IMethodInterceptor> interceptorList = new List<IMethodInterceptor>();

    foreach (Attribute attr in method.GetCustomAttributes(typeof(Attribute), false))
    {
        if(attr is IMethodInterceptor){
            interceptorList.Add((IMethodInterceptor)attr);
        }
    }

    object ret;
    object[] arguments;

    if (interceptorList.Count == 0)
    {
        arguments = callMsg.Args;
        ret = method.Invoke(target, callMsg.Args);
    }
    else
    {
        IMethodInterceptor[] interceptors = interceptorList.ToArray();

        MethodInvocationImpl invocation = new MethodInvocationImpl(target, msg, interceptors);
        ret = interceptors[0].Invoke(invocation);
        arguments = invocation.Arguments;
    }

    IMethodReturnMessage mrm = 
        new ReturnMessage(ret, callMsg.Args, callMsg.Args.Length, callMsg.LogicalCallContext, callMsg);

    return mrm;

}

で、InterceptorのInvokeから呼ばれるMethodInvocation#Proceed()の処理はこんな感じ。

public object Proceed()
{
    while (_interceptorsIndex < _interceptors.Length)
    {
        return _interceptors[_interceptorsIndex++].Invoke(this);
    }
    return Method.Invoke(Target, Arguments);
}

ネストしてるInterceptor分ループさせると。
ほんとみてみれば単純明快な実装でしたとさ。


オープンソースなS2AOPに感謝。