8

Action で呼び出されたメソッドに MyCustomAttibute があるかどうかを確認するために、Action デリゲートで呼び出されたメソッドの MethodInfo を取得する必要があります。

    public void Foo( Action action )
    {
        if(Attribute.GetCustomAttributes(action.Method, typeof(MyCustomAttribute)).Count() == 0)
        {
            throw new ArgumentException("Invalid action");
        }
    }

Foo メソッドは次のように呼び出せるはずです。

    Foo(() =>
    {
            instanceOfFooClass.Method1().Method2();
    });

Foo メソッドでは、Method1 と Method2 に MyCustomAttribute があることを確認したいと思います。ただし、 action.Method は、ラムダ式を使用するときに発生するデリゲートのアクションである MethodInfo を提供しています。Method1 と Method2 の MethodInfo を取得する方法はありますか?

4

2 に答える 2

5

コメントで述べたように、Expression<T>これを達成するためのおそらく最良の方法です。ただし、Compile()実行時にatが必要なため、パフォーマンスプロファイルを作成する必要があります。

これによりExpression<T>、次のようなメソッド情報に簡単にアクセスできます。

public MethodInfo GetMethodInfo(Expression<Action> action)
{
    return ((MethodCallExpression)action.Body).Method;
}

ただし、アクションを実行する前に、次のことを行う必要があります。

private void InvokeMethod(Expression<Action> action)
{
    action.Compile().Invoke();
}

編集 ああ、はい、顧客属性にアクセスする方法を忘れました。あなたはこのようにそれをするでしょう:

var methodInfo = ((MethodCallExpression)myAction.Body).Method;
var attributes = methodInfo.GetCustomAttributes<T>(true);

次 に、連鎖メソッド呼び出しをExpression<Action>次の場所に渡す例を示します。

public class ActionTest
{
    public void DoAction(Action action)
    {
        action();
    }

    public void DoExpressionAction(Expression<Action> action)
    {
        var method2Info = ((MethodCallExpression)action.Body).Method;

        // a little recursion needed here
        var method1Info = ((MethodCallExpression)((MethodCallExpression)action.Body).Object).Method;

        var myattributes2 = method2Info.GetCustomAttributes(typeof(MyAttribute), true);
        var myattributes1 = method1Info.GetCustomAttributes(typeof(MyAttribute), true);

        action.Compile().Invoke();
    }
}

[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
    private string message;

    public MyAttribute(string message)
    {
        this.message = message;
    }
}

public class MethodTest
{
    [MyAttribute("Number1")]
    public MethodTest Method1()
    {
        Console.WriteLine("Action");
        return this;
    }

    [MyAttribute("Number2")]
    public MethodTest Method2()
    {
        Console.WriteLine("ExpressionAction");
        return this;
    }
}


class Program
{
    static void Main(string[] args)
    {
        ActionTest target = new ActionTest();
        MethodTest instance = new MethodTest();

        target.DoExpressionAction(() => instance.Method1().Method2() );

        Console.ReadLine();
    }

    static void Method1()
    {
        Console.WriteLine("Action");
    }

    static void Method2()
    {
        Console.WriteLine("ExpressionAction");
    }
}
于 2012-06-06T11:04:13.443 に答える
4

次のようにメソッドを呼び出す場合Foo()

Foo(instanceOfFooClass.Method);

コードは期待どおりに動作します (void メソッドアクションです)。ちなみに、「連鎖」メソッド呼び出しは、実際には最後の呼び出しのみを通過していると見なされると思います。

動作を示す完全なサンプル:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication4
{
    class MyCustomAttribute : Attribute { }
    class FooClass
    {
        [MyCustom]
        public void DecoratedMethod() { Console.WriteLine("Decorated Method - executed."); }
        public void NotDecoratedMethod() { Console.WriteLine("Not Decoreated Method - executed."); }
    }

    class Program
    {
        static void Main(string[] args)
        {
            FooClass instanceOfFooClass = new FooClass();
            Foo(instanceOfFooClass.DecoratedMethod);
            Foo(instanceOfFooClass.NotDecoratedMethod);
            Console.ReadLine();
        }

        public static void Foo(Action action)
        {
            if (Attribute.GetCustomAttributes(action.Method, typeof(MyCustomAttribute)).Count() == 0)
                Console.WriteLine(string.Format("Invalid method {0}", action.Method.Name));
            else
            {
                Console.WriteLine(string.Format("Valid method {0}", action.Method.Name));
                action.Invoke();
            }
        }
    }
}
于 2012-06-06T11:50:40.753 に答える