[seasar-dotnet:356] S2Container.NET上でのInterceptorChainについて

kk koya-tsuti2 @ u01.gate01.com
2006年 10月 1日 (日) 13:16:19 JST


初めまして。
小谷と申します。
いつもお世話になっております。

表題の件について要望があります。
現在S2Container(Java版)の方にのみ実装されている
InterceptorChainの機能をS2Container.NETの方にも
移植していただけないでしょうか。

私の方でも、Java版のクラスを参考に以下の
ソースコードを試しに書いてみました。
・Seasar.Framework.Aop.Interceptors.InterceptorChain
・Seasar.Framework.Aop.Impl.NestedMethodInvocation
・Seasar.Framework.Util.ArrayUtil
・Seasar.Tests.Framework.Aop.Interceptors.InterceptorChainTest

○InterceptorChain ---------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using Seasar.Framework.Aop;
using Seasar.Framework.Aop.Impl;
using Seasar.Framework.Util;

namespace Seasar.Framework.Aop.Interceptors
{
    /// <summary>
    /// Interceptor collection
    /// </summary>
    public class InterceptorChain : AbstractInterceptor{
        private IMethodInterceptor[] interceptors = new
IMethodInterceptor[0];

   	/// <summary>
        /// Add an interceptor
        /// </summary>
        /// <param name="interceptor"></param>
        public void Add(IMethodInterceptor interceptor) {
            interceptors = (IMethodInterceptor[])ArrayUtil.Add(
                interceptors, interceptor);
        }

        /// <summary>
        /// Execute registed interceptors
        /// </summary>
        /// <param name="invocation"></param>
        /// <returns></returns>
        public override Object Invoke(IMethodInvocation invocation) {
            IMethodInvocation nestInvocation = new NestedMethodInvocation(
                (IS2MethodInvocation)invocation, interceptors);
            return nestInvocation.Proceed();
        }
    }
}
-------------------------------------------------------------
○NestedMethodInvocation  -----------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Seasar.Framework.Aop;

namespace Seasar.Framework.Aop.Impl
{
    /// <summary>
    /// NestedMethodInvocation
    /// </summary>
  public class NestedMethodInvocation : IS2MethodInvocation{
        private readonly IS2MethodInvocation parent;

        private readonly IMethodInterceptor[] interceptors;
        private int interceptorIndex = 0;

        public NestedMethodInvocation(IS2MethodInvocation parent,
            IMethodInterceptor[] interceptors) {
            this.parent = parent;
            this.interceptors = interceptors;
        }

        #region IS2MethodInvocationメンバ

        public Object[] Arguments {
            get {
                return parent.Arguments;
            }
        }

        public MethodBase Method {
            get {
                return parent.Method;
            }
        }

        public Object Target {
            get {
                return parent.Target;
            }
        }

        public Type TargetType {
            get {
                return parent.TargetType;
            }
        }

        public Object Proceed() {
            if (interceptorIndex < interceptors.Length ) {
                return interceptors[interceptorIndex++].Invoke(this);
            }
            return parent.Proceed();
        }

        public Object GetParameter(String name) {
            return parent.GetParameter(name);
        }

        #endregion
    }
}
-------------------------------------------------------
○ArrayUtil -------------------------------------------------
using System;
using System.Collections;
using System.Text;
using Seasar.Framework.Exceptions;

namespace Seasar.Framework.Util
{
    /// <summary>
    /// Utility of array
    /// </summary>
    public class ArrayUtil
    {
        private ArrayUtil() {
        }

        /// <summary>
        /// Add an item to array
        /// </summary>
        /// <param name="array"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Object[] Add(Object[] array, Object obj){
            if( array == null ){
                throw new EmptyRuntimeException("array");
            }
            Object[] newArray = (Object[])Array.CreateInstance(
                array.GetType().GetElementType(), array.Length + 1);
            Array.Copy(array, 0, newArray, 0, array.Length);
            newArray[array.Length] =
(Seasar.Framework.Aop.IMethodInterceptor)obj;
            return newArray;
        }

        /// <summary>
        /// Add an array to another array
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static Object[] Add(Object[] a, Object[] b) {
            if (a != null && b != null) {
                if (a.Length != 0 && b.Length != 0) {
                    Object[] array = (Object[])Array.CreateInstance(
                        a.GetType().GetElementType(), a.Length + b.Length);
                    Array.Copy(a, 0, array, 0, a.Length);
                    Array.Copy(b, 0, array, a.Length, b.Length);
                    return array;
                } else if (b.Length == 0) {
                    return a;
                } else {
                    return b;
                }
            } else if (b == null) {
                return a;
            } else {
                return b;
            }
        }

        /// <summary>
        /// Index of array which is object
        /// </summary>
        /// <param name="array"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static int IndexOf(Object[] array, Object obj) {
            if (array != null) {
                return Array.IndexOf(array, obj);
            }
            return -1;
        }

        /// <summary>
        /// Index of array which is char
        /// </summary>
        /// <param name="array"></param>
        /// <param name="ch"></param>
        /// <returns></returns>
        public static int IndexOf(char[] array, char ch) {
            if (array != null) {
                for (int i = 0; i < array.Length; ++i) {
                    char c = array[i];
                    if (ch == c) {
                        return i;
                    }
                }
            }
            return -1;
        }

        /// <summary>
        /// Remove an object from array
        /// </summary>
        /// <param name="array"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Object[] Remove(Object[] array, Object obj) {
            int index = IndexOf(array, obj);
            if (index < 0) {
                return array;
            }
            Object[] newArray = (Object[])Array.CreateInstance(
                array.GetType(), array.Length - 1);
            if (index > 0) {
                Array.Copy(array, 0, newArray, 0, index);
            }
            if (index < array.Length - 1) {
                Array.Copy(array, index + 1, newArray, index,
                    newArray.Length - index);
            }
            return newArray;
        }

        public static bool IsEmpty(Object[] arrays) {
            return (arrays == null || arrays.Length == 0);
        }

        public static bool Contains(Object[] array, Object obj) {
            return (-1 < IndexOf(array, obj));
        }

        public static bool Contains(char[] array, char ch) {
            return (-1 < IndexOf(array, ch));
        }
    }
}
----------------------------------------------------------------
○InterceptorChainTest -----------------------------------------
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Seasar.Framework.Aop;
using Seasar.Framework.Aop.Impl;
using Seasar.Framework.Aop.Proxy;
using Seasar.Framework.Aop.Interceptors;

namespace Seasar.Tests.Framework.Aop.Interceptors
{
    [TestFixture]
    public class InterceptorChainTest
    {
        private InterceptorChain target = null;

        public static object CreateProxy(IMethodInterceptor interceptor,
Type proxyType) {
            IAspect aspect = new AspectImpl(interceptor, null);
            return new AopProxy(proxyType, new IAspect[] { aspect
}).GetTransparentProxy();
        }

        [SetUp]
        public void SetUp() {
            target = new InterceptorChain();
            IMethodInterceptor interceptor1 = new TestInterceptor("_A");
            IMethodInterceptor interceptor2 = new TestInterceptor("_B");
            IMethodInterceptor interceptor3 = new
MockInterceptor(TestMessage4InterceptorChain.ECHO);
            target.Add(interceptor1);
            target.Add(interceptor2);
            target.Add(interceptor3);
        }

        [Test]
        public void TestInvoke() {
            GoodMorning gm = CreateProxy(target, typeof(GoodMorning)) as
GoodMorning;
            string result = gm.Greeting();
            Console.WriteLine(result);
            Assert.AreEqual(TestMessage4InterceptorChain.ECHO, result);
        }
    }

    public class TestMessage4InterceptorChain
    {
        public const string MSG = "hello";
        public const string ECHO = "echo";
    }

    public interface GoodMorning
    {
        string Greeting();
    }

    public class TestInterceptor : AbstractInterceptor
    {
        #region IMethodInterceptor クラス

        private readonly log4net.ILog _log =
log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private string _id = "";

        public TestInterceptor(string id) {
            _id = id;
        }

        public override object Invoke(IMethodInvocation invocation) {
            Console.WriteLine(string.Format("{0} is called.",
this.ToString() + _id));
            return invocation.Proceed();
        }

        #endregion
    }
}
------------------------------------------------------------

以上です。
よろしくお願い致します。

==========================================
小谷 圭
kotani.k @ buildsystem.jp
koya-tsuti2 @ u01.gate01.com
==========================================



seasar-dotnet メーリングリストの案内