C# 检查属性是否具有属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2051065/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 23:01:25  来源:igfitidea点击:

Check if property has attribute

c#performance

提问by Otávio Décio

Given a property in a class, with attributes - what is the fastest way to determine if it contains a given attribute? For example:

给定一个类中的属性,具有属性 - 确定它是否包含给定属性的最快方法是什么?例如:

    [IsNotNullable]
    [IsPK]
    [IsIdentity]
    [SequenceNameAttribute("Id")]
    public Int32 Id
    {
        get
        {
            return _Id;
        }
        set
        {
            _Id = value;
        }
    }

What is the fastest method to determine that for example it has the "IsIdentity" attribute?

确定例如它具有“IsIdentity”属性的最快方法是什么?

采纳答案by Hans Passant

There's no fast way to retrieve attributes. But code ought to look like this (credit to Aaronaught):

没有快速的方法来检索属性。但是代码应该是这样的(归功于Aaronaught):

var t = typeof(YourClass);
var pi = t.GetProperty("Id");
var hasIsIdentity = Attribute.IsDefined(pi, typeof(IsIdentity));

If you need to retrieve attribute properties then

如果您需要检索属性属性,则

var t = typeof(YourClass);
var pi = t.GetProperty("Id");
var attr = (IsIdentity[])pi.GetCustomAttributes(typeof(IsIdentity), false);
if (attr.Length > 0) {
    // Use attr[0], you'll need foreach on attr if MultiUse is true
}

回答by Darin Dimitrov

If you are using .NET 3.5 you might try with Expression trees. It is safer than reflection:

如果您使用的是 .NET 3.5,您可以尝试使用表达式树。它比反射更安全:

class CustomAttribute : Attribute { }

class Program
{
    [Custom]
    public int Id { get; set; }

    static void Main()
    {
        Expression<Func<Program, int>> expression = p => p.Id;
        var memberExpression = (MemberExpression)expression.Body;
        bool hasCustomAttribute = memberExpression
            .Member
            .GetCustomAttributes(typeof(CustomAttribute), false).Length > 0;
    }
}

回答by Manish Basantani

You can use a common (generic) method to read attribute over a given MemberInfo

您可以使用通用(通用)方法读取给定 MemberInfo 上的属性

public static bool TryGetAttribute<T>(MemberInfo memberInfo, out T customAttribute) where T: Attribute {
                var attributes = memberInfo.GetCustomAttributes(typeof(T), false).FirstOrDefault();
                if (attributes == null) {
                    customAttribute = null;
                    return false;
                }
                customAttribute = (T)attributes;
                return true;
            }

回答by Seb

To update and/or enhance the answer by @Hans Passant I would separate the retrieval of the property into an extension method. This has the added benefit of removing the nasty magic string in the method GetProperty()

为了更新和/或增强@Hans Passant 的答案,我会将属性的检索分离为一个扩展方法。这具有移除方法 GetProperty() 中令人讨厌的魔法字符串的额外好处

public static class PropertyHelper<T>
{
    public static PropertyInfo GetProperty<TValue>(
        Expression<Func<T, TValue>> selector)
    {
        Expression body = selector;
        if (body is LambdaExpression)
        {
            body = ((LambdaExpression)body).Body;
        }
        switch (body.NodeType)
        {
            case ExpressionType.MemberAccess:
                return (PropertyInfo)((MemberExpression)body).Member;
            default:
                throw new InvalidOperationException();
        }
    }
}

Your test is then reduced to two lines

你的测试然后减少到两行

var property = PropertyHelper<MyClass>.GetProperty(x => x.MyProperty);
Attribute.IsDefined(property, typeof(MyPropertyAttribute));

回答by Has AlTaiar

If you are trying to do that in a Portable Class Library PCL (like me), then here is how you can do it :)

如果您尝试在可移植类库 PCL 中执行此操作(像我一样),那么您可以这样做:)

public class Foo
{
   public string A {get;set;}

   [Special]
   public string B {get;set;}   
}

var type = typeof(Foo);

var specialProperties = type.GetRuntimeProperties()
     .Where(pi => pi.PropertyType == typeof (string) 
      && pi.GetCustomAttributes<Special>(true).Any());

You can then check on the number of properties that have this special property if you need to.

然后,如果需要,您可以检查具有此特殊属性的属性数量。

回答by Mark Schultheiss

This is a pretty old question but I used

这是一个很老的问题,但我用过

My method has this parameter but it could be built:

我的方法有这个参数,但它可以被构建:

Expression<Func<TModel, TValue>> expression

Then in the method this:

然后在方法中:

System.Linq.Expressions.MemberExpression memberExpression 
       = expression.Body as System.Linq.Expressions.MemberExpression;
Boolean hasIdentityAttr = System.Attribute
       .IsDefined(memberExpression.Member, typeof(IsIdentity));

回答by Jim Wolff

This can now be done without expression trees and extension methods in a type safe manner with the new C# feature nameof()like this:

现在可以使用新的 C# 功能以类型安全的方式在没有表达式树和扩展方法的情况下完成此操作,nameof()如下所示:

Attribute.IsDefined(typeof(YourClass).GetProperty(nameof(YourClass.Id)), typeof(IsIdentity));

nameof()was introduced in C# 6

nameof()是在 C# 6 中引入的

回答by Francis Musignac

You can use the Attribute.IsDefined method

您可以使用 Attribute.IsDefined 方法

https://msdn.microsoft.com/en-us/library/system.attribute.isdefined(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/system.attribute.isdefined(v=vs.110).aspx

if(Attribute.IsDefined(YourProperty,typeof(YourAttribute)))
{
    //Conditional execution...
}

You could provide the property you're specifically looking for or you could iterate through all of them using reflection, something like:

您可以提供您专门寻找的属性,也可以使用反射遍历所有属性,例如:

PropertyInfo[] props = typeof(YourClass).GetProperties();