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

发布于 2024-09-14 16:59:35 字数 337 浏览 5 评论 0原文

抱歉,如果这是一个愚蠢的菜鸟问题,请对我温柔一点,我正在努力学习......

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

我想要的是一种方法,在实现时看起来有点像

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

我使用过的扩展方法,但没有达到这种程度。我确信这应该足够简单,但似乎无法让我的泛型等正确。

Sorry if this is a stupid noob question please be gentle with me I'm trying to learn...

I want to test against the attribute methods of things like models and controllers. Mostly to make sure they have the right attrbute ie Required. But i'm also using this as an experiment with extension methods and Lambdas.

What I'd like is a method that when implimented looks some thing like

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

Iveused extension methods a little but not to this degree.. I'm sure this should be simple enough to do but cant seem to get my generics etc correct.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

野侃 2024-09-21 16:59:35

也许您正在寻找这个:

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

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

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

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

Perhaps you are looking for this:

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

What's nice about writing it like this is that you have fully compile time support. All other solutions thus far use string literals to define the methods.

Here are the implementations of the GetMethod and HasAttribute<T> extension methods:

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;
}
ぃ弥猫深巷。 2024-09-21 16:59:35

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

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

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

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

 controller.MethodHasAttribute(methodName, attributeName);

I don't think you'll be able to implement that exactly as you described. The MethodName(params) part of your statement will actually execute the method, returning whatever the method returns, and not information about the method.

What you want to do is pass in a MethodInfo into your extension class, using reflection. So instead of your example, you'd probably end up with something like:

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

You could probably simplify this down to a single extension method on the controller class by encapsulating GetType().GetMethod(), like so:

 controller.MethodHasAttribute(methodName, attributeName);
情定在深秋 2024-09-21 16:59:35

使用扩展方法无法完全做到这一点,但这已经很接近了:

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

Can't quite do exactly that with extension methods, but this is close:

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()
  {
  }
}
渔村楼浪 2024-09-21 16:59:35

用法:

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

Usage:

bool hasAttribute = controller.HasMethodAttribute<TestAttribute>( "Test" )

Extension:

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 ;
} 
七秒鱼° 2024-09-21 16:59:35

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

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

You can check whether a method has a particular attribute by doing this:

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

In terms of the extension method itself, provided that you're looking for an extension method on the Controller type, how about something like this:

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

Remember, extension methods are invoked on an instance, so to use this you still need an instance of Controller:

var controller = new Controller();
Assert.IsTrue(controller.HasAttribute<AttributeName>("Method1"));
青瓷清茶倾城歌 2024-09-21 16:59:35

您正在寻找 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);
    }
}

You're looking for the Reflection class - it allows you to examine a passed object.

But frankly other than a learning exercise this is what Interfaces exist for, if you want there to be a field called Required in a model, or a method called IsRequired in a controller than implement in an interface and require that interface be implemented.

Specifically for attributes see 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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文