如何检查方法是否具有属性
我有一个示例类
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 的 。现在我怎样才能以一种将字符串和类作为参数的方式来实现这个通用呢?
I have an example class
public class MyClass{
ActionResult Method1(){
....
}
[Authorize]
ActionResult Method2(){
....
}
[Authorize]
ActionResult Method3(int value){
....
}
}
Now what I want is to write a function returning true/false that can be executed like this
var controller = new MyClass();
Assert.IsFalse(MethodHasAuthorizeAttribute(controller.Method1));
Assert.IsTrue(MethodHasAuthorizeAttribute(controller.Method2));
Assert.IsTrue(MethodHasAuthorizeAttribute(controller.Method3));
I got to the point where
public bool MethodHasAuthorizeAttribute(Func<int, ActionResult> function)
{
return function.Method.GetCustomAttributes(typeof(AuthorizeAttribute), false).Length > 0;
}
would work for Method3. Now how can I do that generic in a way that it'll take strings and classes as parameters as well?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您的代码的问题是
public bool MethodHasAuthorizeAttribute(Funcfunction)
的签名。MethodHasAuthorizeAttribute
只能与与您指定的委托签名匹配的参数一起使用。在本例中,方法返回带有int
类型参数的ActionResult
。当您调用此方法(如
MethodHasAuthorizeAttribute(controller.Method3)
)时,编译器将执行方法组转换。这可能并不总是理想的,并且可能会产生意想不到的结果(方法组转换并不总是直接的)。如果您尝试调用MethodHasAuthorizeAttribute(controller.Method1)
,您将收到编译器错误,因为没有转换。可以使用表达式树和著名的“MethodOf”技巧构建更通用的解决方案。它使用编译器生成的表达式树来查找调用目标:
您可以像这样使用它,但它也可以与任何方法一起使用:
有了它,我们就可以构建一个通用实现:
好的,这就是方法。现在,如果您想对类或字段应用属性检查(我将保留属性,因为它们实际上是方法),我们需要对
MemberInfo
执行检查,它是 的继承根类型
、FieldInfo
和MethodInfo
。这就像将属性搜索提取到单独的方法中并提供具有好名称的适当适配器方法一样简单:我将把字段的实现作为练习,您可以采用与 MethodOf 相同的技巧。
The issue with your code is the signature of
public bool MethodHasAuthorizeAttribute(Func<int, ActionResult> function)
.MethodHasAuthorizeAttribute
can only be used with arguments matching the signature of the delegate you specified. In this case a method returning anActionResult
with a parameter of typeint
.When you call this method like
MethodHasAuthorizeAttribute(controller.Method3)
, the Compiler will do a method group conversion. This might not always be desired and can yield unexpected results (Method group conversions aren't always straigthforward). If you try to callMethodHasAuthorizeAttribute(controller.Method1)
you will get a compiler error because there's no conversion.A more general solution can be constructed with expression trees and the famous "MethodOf" trick. It employs compiler generated expression trees to find the invocation target:
You can use it like this, but it can also be used with any method:
With that out of the way, we can build a general implementation:
Okay, thats for methods. Now, if you want to apply the Attribute check on classes or fields to (I'll spare properties because they are actually methods), we need to perform our check on
MemberInfo
, which is the inheritance root forType
,FieldInfo
andMethodInfo
. This as easy as extracting the Attribute search into a separate method and providing appropriate adapter methods with nice names:I'll leave the implementation for fields as an exercise, you can employ the same trick as MethodOf.
与当前 .NET/C# 版本(4.6.1、C#6)的其他解决方案相比,有一种更简单的解决方案:
如果您只有一个具有该名称的方法:
现在检查您是否已设置该属性方法:
如果你想访问属性的属性,你可以简单地做到这一点:
如果有多个同名的方法,你可以继续使用
method.GetParameters()
并检查参数,而不是.GetMethods().Single...
如果您知道您的方法没有参数,则此检查很容易:
如果不知道,这将更加复杂(检查参数等)并且其他解决方案使用起来更简单、更可靠。
因此:如果您没有方法重载,或者只想从具有指定数量参数的方法中读取属性,请使用此方法。
否则,请使用此处其他答案提供的
MethodOf
。There is an easier solution availabe compared to the others above with the current .NET/C# version (4.6.1, C#6):
If you only have one one method with that name:
Now to check if you have the attribute set on the method:
And if you want to access the properties of the attribute, you can do this easy as that:
If there are multiple methods with the same name, you can go on and use
method.GetParameters()
and check for the parameters, instead of.GetMethods().Single...
If you know that your method has no parameters, this check is easy:
If not, this is going to be more complicated (checking parameters, etc.) and the other solutions are way easier and robust to use.
So: Use this if you have no overloads for a method, or only want to read attributes from a method with a specified amount of parameters.
Else, use the
MethodOf
provided by other answers in here.我做了类似的事情:
调用它如下
I do something like that:
Calling it follows
如果您使用 FluentAssertions 您可以执行以下操作:
If you make use of FluentAssertions you can do the following:
查找一些示例,在其中我找到应用了指定属性的类中的方法。
传递的参数是类的实例。您可以修改代码以满足您的要求,这应该很容易。
Find some sample where i find the methods in a class that have a specified attribute applied.
The parameter that is passed is an instance of a class. You can modify the code to suit your requirement which should be pretty easy.