割と普通なブログ

Microsoft Azure や ASP.NET、Java EE 系の話題を記載します

オレオレ Interceptor

ActionMethodSelector.cs辺りを眺めつつ、C#のリフレクション使って細々とInterceptorもどきを書いてみた。

using System;
using System.Linq;
using System.Reflection;

class Program
{
    static void Main(string[] args)
    {
        ConcreteDummyAction obj = new ConcreteDummyAction();

        //継承をたどり、Propertyを排除してMyValidMethodAttribute属性が付与されたメソッドを取得する
        var query = from methodInfo in obj.GetType()
                          .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static)
                    where methodInfo.GetCustomAttributes(typeof(MyValidMethodAttribute), true).Count() > 0
                          && !methodInfo.IsSpecialName
                    select methodInfo;

        //取得したメソッドに対して、OnExcutingとOnExcutedを直前直後に実行する
        query.ToList().ForEach(methodInfo => {
            MyValidMethodAttribute validMethodAttr = methodInfo
                .GetCustomAttributes(typeof(MyValidMethodAttribute), true).First() as MyValidMethodAttribute;
            validMethodAttr.OnExcuting(methodInfo.Name);
            methodInfo.Invoke(obj, null);
            validMethodAttr.OnExcuted(methodInfo.Name);
        });
        Console.ReadLine();
    }
	//ValidActionメソッド実行前
	//この concrete コントロールは有効
	//ValidActionメソッド実行後
	//AbstractValidActionメソッド実行前
	//この abstract action コントロールは有効
	//AbstractValidActionメソッド実行後
}

[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public class MyValidMethodAttribute : Attribute
{
    public void OnExcuted(string methodName)
    {
        Console.WriteLine(methodName+ "メソッド実行後");
    }

    public void OnExcuting(string methodName)
    {
        Console.WriteLine(methodName+ "メソッド実行前");
    }
}

public abstract class AbstractDummyAction
{
    [MyValidMethod]
    public void AbstractValidAction()
    {
        Console.WriteLine("この abstract action コントロールは有効");
    }

    public void AbstractInValidAction()
    {
        Console.WriteLine("この abstract action コントロールは無効");
    }
}


public class ConcreteDummyAction : AbstractDummyAction
{
    public string InvalidName { get; set; }

    [MyValidMethod]
    public void ValidAction()
    {
        Console.WriteLine("この concrete コントロールは有効");
    }

    public void InValidAction()
    {
        Console.WriteLine("この concrete コントロールは有効");
    }
}