3

我想编写一个方法来分析任何方法的自定义属性(具有任意数量的参数和任何返回类型),只知道方法信息。此函数将检查方法是否具有特定属性。像这样:var tmp = methodInfo.GetCustomAttributes(typeof(LineItemAttribute),false);如果它具有这样的属性,它将执行它。我想让该函数的调用非常易于使用。GetMethodAttributes因此,在示例中,我想调用三种方法和方法。

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...
        }
    }
}

这使用了两个实用程序类,用于从给定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执行类似的操作,在其中通过 lambda 表达式传递方法。但是,您仍然需要为参数传递存根值。有关此操作的一个很好的示例,请查看Moq的源代码,它广泛使用此模式来设置单元测试的模拟行为。请注意,这不是一件容易设置的事情。如果你需要一些相对快速和肮脏的东西,你最好的选择可能是使用良好的重构工具和/或自动化测试来帮助处理重命名问题的字符串名称。

于 2013-01-15T01:21:48.660 回答