C#用于检查属性的扩展方法
对不起,如果这是一个愚蠢的菜鸟问题,请温柔地对待我,我正在努力学习……
我想测试模型和控制器之类的属性方法。 主要是为了确保他们有正确的属性,即必需。 但我也将它用作扩展方法和Lambdas的实验。
我想要的是一种方法,当被称赞时看起来有点像
Controller controller = new Controller(); controller.MethodName(params).HasAttribute();
我尝试了一些扩展方法,但没有达到这个程度。我确信这应该很简单,但似乎无法使我的generics等正确。
也许你正在寻找这个:
Controller controller = new Controller(); bool ok = controller.GetMethod(c => c.MethodName(null, null)) .HasAttribute();
像这样编写它的好处是你有完全编译时间支持。 到目前为止,所有其他解决方案都使用字符串文字来定义方法。
以下是GetMethod
和HasAttribute
扩展方法的实现:
public static MethodInfo GetMethod(this T instance, Expression> methodSelector) { // Note: this is a bit simplistic implementation. It will // not work for all expressions. return ((MethodCallExpression)methodSelector.Body).Method; } public static MethodInfo GetMethod (this T instance, Expression> methodSelector) { return ((MethodCallExpression)methodSelector.Body).Method; } public static bool HasAttribute( this MemberInfo member) where TAttribute : Attribute { return GetAttributes (member).Length > 0; } public static TAttribute[] GetAttributes ( this MemberInfo member) where TAttribute : Attribute { var attributes = member.GetCustomAttributes(typeof(TAttribute), true); return (TAttribute[])attributes; }
我认为你无法完全按照你的描述实施。 语句的MethodName(params)
部分实际上将执行该方法,返回方法返回的任何内容,而不是有关该方法的信息。
您要做的是使用reflection将MethodInfo
传递到您的扩展类中。 所以不是你的例子,你可能会得到类似的东西:
controller.GetType().GetMethod(methodName).HasAttribute();
您可以通过封装GetType().GetMethod()
来简化控制器类上的单个扩展方法,如下所示:
controller.MethodHasAttribute(methodName, attributeName);
使用扩展方法无法做到这一点,但这很接近:
public static class Program { static void Main(string[] args) { Controller c1 = new Controller(); Action a1 = c1.Method1; Console.WriteLine(a1.HasAttribute()); } public static bool HasAttribute(this Action method) { return method.Method.GetCustomAttributes(typeof(T), false).Any(); } } class Controller { [AttributeUsage(AttributeTargets.Method)] public class TestAttribute : System.Attribute { } [Test()] public void Method1() { } }
用法:
bool hasAttribute = controller.HasMethodAttribute( "Test" )
延期:
public static bool HasMethodAttribute( this object obj, string methodName ) { Type type = obj.GetType(); MethodInfo method = type.GetMethod( methodName ); if( method == null ) { throw new ArgumentException( string.Format( "Method '{0}' not found on object '{1}'", methodName, type.Name ) ); } return method.GetCustomAttributes( typeof( TAttribute ), true ).Length > 0 ; }
您可以通过执行以下操作来检查方法是否具有特定属性:
typeof(Controller).GetMethod("MethodName").GetAttributes().Any();
就扩展方法本身而言,如果您正在寻找Controller类型的扩展方法,那么这样的事情如何:
public static bool HasAttribute(this Controller controller, string methodName) { return controller.GetType().GetMethod(methodName).GetCustomAttributes(typeof(A), true).Any(); }
请记住,在实例上调用扩展方法,因此要使用它,您仍需要一个Controller实例:
var controller = new Controller(); Assert.IsTrue(controller.HasAttribute("Method1"));
您正在寻找Reflection类 – 它允许您检查传递的对象。
但坦率地说,除了学习练习之外,这就是接口的存在,如果你希望在模型中有一个名为Required的字段,或者在控制器中使用一个名为IsRequired的方法,而不是在接口中实现并要求实现接口。
具体针对属性请参见此处 :
Type t = something; System.Console.WriteLine("Author information for {0}", t); System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // reflection foreach (System.Attribute attr in attrs) { if (attr is Author) { Author a = (Author)attr; System.Console.WriteLine(" {0}, version {1:f}", a.GetName(), a.version); } }