C#用于检查属性的扩展方法

时间:2010-08-13 12:27:54

标签: c# tdd extension-methods

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

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

我想要的是一种方法,当被赋予某种东西时会看起来像

Controller controller = new Controller();
controller.MethodName(params).HasAttribute<AttributeName>();

稍微使用了扩展方法,但没有达到这个程度。我确信这应该很简单,但似乎无法使我的泛型等正确。

6 个答案:

答案 0 :(得分:19)

也许您正在寻找这个:

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

这样编写它的好处是你有完全编译时间支持。到目前为止,所有其他解决方案都使用字符串文字来定义方法。

以下是GetMethodHasAttribute<T>扩展方法的实现:

public static MethodInfo GetMethod<T>(this T instance,
    Expression<Func<T, object>> methodSelector)
{
    // Note: this is a bit simplistic implementation. It will
    // not work for all expressions.
    return ((MethodCallExpression)methodSelector.Body).Method;
}

public static MethodInfo GetMethod<T>(this T instance,
    Expression<Action<T>> methodSelector)
{
    return ((MethodCallExpression)methodSelector.Body).Method;
}

public static bool HasAttribute<TAttribute>(
    this MemberInfo member) 
    where TAttribute : Attribute
{
    return GetAttributes<TAttribute>(member).Length > 0;
}

public static TAttribute[] GetAttributes<TAttribute>(
    this MemberInfo member) 
    where TAttribute : Attribute
{
    var attributes = 
        member.GetCustomAttributes(typeof(TAttribute), true);

    return (TAttribute[])attributes;
}

答案 1 :(得分:1)

使用扩展方法无法做到这一点,但这很接近:

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()
  {
  }
}

答案 2 :(得分:1)

<强>用法:

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

答案 3 :(得分:1)

我认为你无法完全按照你的描述实施。语句的MethodName(params)部分实际上将执行该方法,返回方法返回的内容,而不是有关方法的信息。

您要做的是使用反射将MethodInfo传入您的扩展程序。因此,您可能最终会得到类似的结果:

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

您可以通过封装GetType().GetMethod()来简化控制器类上的单个扩展方法,如下所示:

 controller.MethodHasAttribute(methodName, attributeName);

答案 4 :(得分:0)

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

typeof(Controller).GetMethod("MethodName").GetAttributes<AttributeName>().Any();

就扩展方法本身而言,如果您正在寻找Controller类型的扩展方法,那么如何:

public static bool HasAttribute<A>(this Controller controller, string methodName)
{
   return controller.GetType().GetMethod(methodName).GetCustomAttributes(typeof(A), true).Any();
}

请记住,在实例上调用扩展方法,因此要使用它,您仍需要一个Controller实例:

var controller = new Controller();
Assert.IsTrue(controller.HasAttribute<AttributeName>("Method1"));

答案 5 :(得分:-1)

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

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

特别是对于属性,请参阅here

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);
    }
}