检查属性的C#扩展方法

检查属性的C#扩展方法,c#,tdd,extension-methods,C#,Tdd,Extension Methods,对不起,如果这是一个愚蠢的问题,请对我温柔一点,我正在努力学习 我想测试模型和控制器之类的属性方法。主要是为了确保他们具有所需的正确属性。但我也将此用作扩展方法和lambda的实验 我想要的是一个方法,当它被实现时,它看起来像 Controller controller = new Controller(); controller.MethodName(params).HasAttribute<AttributeName>(); 控制器=新控制器(); controller.Met

对不起,如果这是一个愚蠢的问题,请对我温柔一点,我正在努力学习

我想测试模型和控制器之类的属性方法。主要是为了确保他们具有所需的正确属性。但我也将此用作扩展方法和lambda的实验

我想要的是一个方法,当它被实现时,它看起来像

Controller controller = new Controller();
controller.MethodName(params).HasAttribute<AttributeName>();
控制器=新控制器();
controller.MethodName(params.HasAttribute();
我使用了一些扩展方法,但没有达到这个程度。。我确信这应该足够简单,但似乎无法正确地获取泛型等。

您正在寻找类-它允许您检查传递的对象

但坦率地说,除了学习练习之外,如果您希望在模型中有一个名为Required的字段,或者在控制器中有一个名为IsRequired的方法,而不是在接口中实现并要求实现该接口,那么接口就是为了这个目的而存在的

具体属性请参见:


通过执行以下操作,可以检查方法是否具有特定属性:

typeof(Controller).GetMethod("MethodName").GetAttributes<AttributeName>().Any();
typeof(Controller.GetMethod(“MethodName”).GetAttributes().Any();
就扩展方法本身而言,如果您正在寻找控制器类型上的扩展方法,那么类似这样的情况如何:

public static bool HasAttribute<A>(this Controller controller, string methodName)
{
   return controller.GetType().GetMethod(methodName).GetCustomAttributes(typeof(A), true).Any();
}
publicstaticboolhassattribute(此控制器,stringmethodname)
{
返回controller.GetType().GetMethod(methodName).GetCustomAttributes(typeof(A),true).Any();
}
请记住,扩展方法是在实例上调用的,因此要使用它,您仍然需要Controller的实例:

var controller = new Controller();
Assert.IsTrue(controller.HasAttribute<AttributeName>("Method1"));
var控制器=新控制器();
Assert.IsTrue(controller.HasAttribute(“Method1”);

我认为您不能完全按照您所描述的那样实现它。语句的
MethodName(params)
部分将实际执行该方法,返回该方法返回的内容,而不是有关该方法的信息

您要做的是使用反射将
MethodInfo
传递到扩展类中。因此,与您的示例不同,您可能会得到以下结果:

 controller.GetType().GetMethod(methodName).HasAttribute<AttributeName>();

使用扩展方法不能完全做到这一点,但这很接近:

public static class Program
{
  static void Main(string[] args)
  {
     Controller c1 = new Controller();
     Action a1 = c1.Method1;
     Console.WriteLine(a1.HasAttribute<Controller.TestAttribute>());
  }

  public static bool HasAttribute<T>(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()
  {
  }
}
公共静态类程序
{
静态void Main(字符串[]参数)
{
控制器c1=新控制器();
动作a1=c1.1;
Console.WriteLine(a1.HasAttribute());
}
公共静态bool HasAttribute(此操作方法)
{
return method.GetCustomAttributes(typeof(T),false).Any();
}
}
类控制器
{
[AttributeUsage(AttributeTargets.Method)]
公共类TestAttribute:System.Attribute
{
}
[测试()]
公共无效方法1()
{
}
}

也许您正在寻找:

Controller controller = new Controller();
bool ok = controller.GetMethod(c => c.MethodName(null, null))
    .HasAttribute<AttributeName>();

用法:

bool hasAttribute = controller.HasMethodAttribute<TestAttribute>( "Test" )
public static bool HasMethodAttribute<TAttribute>( 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 ;
} 
bool hasaAttribute=controller.HasMethodAttribute(“测试”)
扩展名:

bool hasAttribute = controller.HasMethodAttribute<TestAttribute>( "Test" )
public static bool HasMethodAttribute<TAttribute>( 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 ;
} 
public static bool HasMethodAttribute(此对象对象对象,字符串methodName)
{
Type Type=obj.GetType();
MethodInfo method=type.GetMethod(methodName);
if(方法==null)
{
抛出新ArgumentException(string.Format(
在对象{1}上找不到方法{0}(方法名,类型.Name));
}
返回方法.GetCustomAttributes(typeof(tatAttribute),true).Length>0;
} 

我不确定我是否理解,
HasAttribute
是一种扩展方法,它应该能够告诉您
Controller
类的
MethodName
方法是否具有
AttributeName
属性?是的,这正是我想要的。为了单元测试的目的,但也只是为了我作为一名学习实践者,我现在正在思考这个链接。我明白你的意思,这是一个学习练习,但我不想用不必要的界面来干扰我的解决方案。这更像是一个单元测试练习。我知道这可能不是最好的方法,但我似乎喜欢检查授权等东西的想法。干杯,Ryan,我喜欢这种方法,感谢你解释了D'oh从未想过的死刑。很好,我喜欢这一点和Ryan的方法。如果这段代码正在生产中,我想我可能可以从这些/+1中拼凑出一些东西,我肯定需要编译时检查。ps@Jerod为什么要对生产进行编译时检查。只是好奇。不,代码不在生产中。您的意思是不像其他方法那样使用魔术字符串吗?编译时检查在方法名称更改时非常有用。方法名称更改时,必须更改对HasAttribute的调用。如果使用“magic”字符串,则如果该字符串未更改,则在运行时将得到一个expetion。在单元测试环境中,这并没有什么大不了的。我将我的单元测试代码视为生产代码。我觉得它不是二等公民,不应该被这样对待。如果你看我的答案,我会检查以确保方法存在,然后向用户提供更多信息。如果没有这个检查,它将是一个空引用异常。很酷,感谢Jerod的解释。我完全同意单元测试应该是一等公民。是的,我不喜欢“魔术”字符串,这就是为什么我喜欢Lambda和通用方法。不幸的是,我只有少量的经验,并且在一些高级主题(以及基本主题)上遇到了困难。再次感谢您和所有人的帮助。@Jarod:单元测试和编译时支持并不是相互排斥的。我通常测试我的(生产)系统。但我也希望能够轻松地重构代码,尽可能远离神奇的字符串(也在我的ASP.NET标记中)。这样一来,我就可以从一开始就避免考试失败。这节省了我很多时间。
public static bool HasMethodAttribute<TAttribute>( 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 ;
}