3

メソッド情報のみを知っている任意のメソッド(任意の数の引数と任意の戻り値タイプ)のカスタム属性を分析するメソッドを作成したいと思います。この関数は、メソッドに特定の属性があるかどうかをチェックします。このように:var tmp = methodInfo.GetCustomAttributes(typeof(LineItemAttribute),false);そしてそれがそのような属性を持っているならそれはそれを実行しますそして私はその関数の呼び出しを本当に使いやすくしたいと思います。GetMethodAttributesしたがって、例では、呼び出したい3つのメソッドとメソッドがあります。

class Test
{
      public static void Main()
      {
      }

      public void Test1(){}

      public void Test2(int a){}

      public void Test3(object a, string c, Boolean d);

      public void GetMethodAttributes(MethodInfo mi) {}
}

理想的にはそのようなものを書きたい

public static void Main()
    {
        var t = new Test();
        GetMethodAttributes(t.Test1);
        GetMethodAttributes(t.Test2);
        GetMethodAttributes(t.Test3);
    }

メソッド名は次のように変更される可能性があるため、メソッド名の文字列表現を使用したくありません。

MethodInfo info = type.GetMethod(name);

オプションはありますか?基本的に、異なる正弦関数を持つ関数にデリゲートを使用する方法が必要です

4

2 に答える 2

4

クリス・シンクレアが上のコメントで指摘したように、リフレクションまたは式ツリーを使用せずにデリゲートを使用して、を取得できますMethodInfo。欠点は、コンパイラがジェネリックパラメータを推測できないため、次のように、指定されたメソッドのシグネチャと一致するようにデリゲートタイプを指定する必要があることです。

public class Test
{
    public static void Main()
    {
        var t = new Test();
        CheckMethodAttributes<Action>(t.Test1);
        CheckMethodAttributes<Action<int>>(t.Test2);
        CheckMethodAttributes<Action<object, string, bool>>(t.Test3);
    }

    public void Test1() { }

    public void Test2(int a) { }

    public void Test3(object a, string c, bool d) { }

    public static void CheckMethodAttributes<T>(T func)
    {
        MethodInfo method = new MethodOf<T>(func);

        // Example attribute check:
        var ignoreAttribute = method.GetAttribute<IgnoreAttribute>();
        if (ignoreAttribute != null)
        {
            // Do something here...
        }
    }
}

これは、2つのユーティリティクラスを使用します。指定されたものからMethodOf<T>を抽出するためのものと、強く型付けされたカスタム属性を取得するためのものです。MethodInfoDelegateAttributeUtils

public static class AttributeUtils
{
    public static bool HasAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
        where TAttribute : Attribute
    {
        return member.IsDefined(typeof(TAttribute), inherit);
    }

    public static TAttribute GetAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
        where TAttribute : Attribute
    {
        return member.GetAttributes<TAttribute>(inherit).FirstOrDefault();
    }

    public static IEnumerable<TAttribute> GetAttributes<TAttribute>(this MemberInfo member, bool inherit = true)
        where TAttribute : Attribute
    {
        return member.GetCustomAttributes(typeof(TAttribute), inherit).Cast<TAttribute>();
    }
}

public class MethodOf<T>
{
    public MethodOf(T func)
    {
        var del = func as Delegate;
        if (del == null) throw new ArgumentException("Cannot convert func to Delegate.", "func");

        Method = del.Method;
    }

    private MethodInfo Method { get; set; }

    public static implicit operator MethodOf<T>(T func)
    {
        return new MethodOf<T>(func);
    }

    public static implicit operator MethodInfo(MethodOf<T> methodOf)
    {
        return methodOf.Method;
    }
}
于 2013-01-15T12:38:41.643 に答える
2

ラムダ式を介してメソッドを渡すExpression Treesを使用して、このようなことを行うことができます。ただし、パラメーターのスタブ値を渡す必要はあります。この動作の良い例については、Moqのソース コードを確認してください。これは、単体テスト用のモック動作を設定するためにこのパターンを広範に使用しています。これは簡単な設定ではないことに注意してください。比較的迅速で汚いものが必要な場合は、名前変更の問題に対処するのに役立つ優れたリファクタリング ツールや自動テストを備えた文字列名が最善の策です。

于 2013-01-15T01:21:48.660 に答える