c# - 如何检查方法是否具有属性

标签 c# reflection attributes tdd assert

我有一个示例类

public class MyClass{

    ActionResult Method1(){
        ....
    } 

    [Authorize]
    ActionResult Method2(){
       ....
    }

    [Authorize]    
    ActionResult Method3(int value){
       ....
    }

}

现在我想要的是编写一个可以像这样执行的返回 true/false 的函数

var controller = new MyClass();

Assert.IsFalse(MethodHasAuthorizeAttribute(controller.Method1));
Assert.IsTrue(MethodHasAuthorizeAttribute(controller.Method2));
Assert.IsTrue(MethodHasAuthorizeAttribute(controller.Method3));

我到了那个地步

public bool MethodHasAuthorizeAttribute(Func<int, ActionResult> function)
{
    return function.Method.GetCustomAttributes(typeof(AuthorizeAttribute), false).Length > 0;
}

适用于 Method3。现在我怎样才能以一种将字符串和类也作为参数的方式来实现泛型?

最佳答案

您的代码的问题是 public bool MethodHasAuthorizeAttribute(Func<int, ActionResult> function) 的签名. MethodHasAuthorizeAttribute只能与与您指定的委托(delegate)人的签名相匹配的参数一起使用。在这种情况下,返回 ActionResult 的方法参数类型为 int .

当您像 MethodHasAuthorizeAttribute(controller.Method3) 这样调用此方法时, 编译器将进行方法组转换。这可能并不总是需要的,并且会产生意想不到的结果(方法组转换并不总是直接的)。如果您尝试调用 MethodHasAuthorizeAttribute(controller.Method1)你会得到一个编译器错误,因为没有转换。

可以使用表达式树和著名的“MethodOf”技巧构建更通用的解决方案。它使用编译器生成的表达式树来查找调用目标:

public static MethodInfo MethodOf( Expression<System.Action> expression )
{
    MethodCallExpression body = (MethodCallExpression)expression.Body;
    return body.Method;
}

你可以像这样使用它,但它也可以与任何方法一起使用:

MethodInfo method = MethodOf( () => controller.Method3( default( int ) ) );

有了这个,我们就可以构建一个通用的实现:

public static bool MethodHasAuthorizeAttribute( Expression<System.Action> expression )
{
    var method = MethodOf( expression );

    const bool includeInherited = false;
    return method.GetCustomAttributes( typeof( AuthorizeAttribute ), includeInherited ).Any();
}

好的,这就是方法。现在,如果您想对类或字段应用属性检查(我将保留属性,因为它们实际上是方法),我们需要对 MemberInfo 执行检查,这是 Type 的继承根, FieldInfoMethodInfo .这就像将属性搜索提取到一个单独的方法中并提供具有漂亮名称的适当适配器方法一样简单:

public static bool MethodHasAuthorizeAttribute( Expression<System.Action> expression )
{
    MemberInfo member = MethodOf( expression );
    return MemberHasAuthorizeAttribute( member );
}

public static bool TypeHasAuthorizeAttribute( Type t)
{
    return MemberHasAuthorizeAttribute( t );
}

private static bool MemberHasAuthorizeAttribute( MemberInfo member )
{
    const bool includeInherited = false;
    return member.GetCustomAttributes( typeof( AuthorizeAttribute ), includeInherited ).Any();
}

我将字段的实现留作练习,您可以使用与 MethodOf 相同的技巧。

关于c# - 如何检查方法是否具有属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8817031/

相关文章:

perl - "Can' t 修改非左值子程序调用"当从方法中添加 Moose 属性时

c# - 读取派生类的属性值

c# - WP7中父列表框垂直滚动时如何锁定水平滚动

.net - 如何获取 CLR 加载的类型列表?

c# - 如何从 TextBox 中删除最后一个字符?

scala - 如何获取Scala函数的参数/返回类型?

go - 遍历具有嵌入结构的结构

python - 连接作为 python 中的类实例属性的 numpy 数组

c# - 如何避免在 linq 中加载特定列

c# - 树算法实现c#