簡體   English   中英

檢查屬性是否具有屬性

[英]Check if property has attribute

給定類中的屬性,使用屬性 - 確定它是否包含給定屬性的最快方法是什么? 例如:

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

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

沒有快速的方法來檢索屬性。 但代碼應該看起來像這樣(歸功於Aaronaught ):

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

如果您需要檢索屬性屬性

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
}

如果您使用的是.NET 3.5,則可以嘗試使用Expression樹。 它比反思更安全:

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

您可以使用公共(通用)方法讀取給定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;
            }

要通過@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();
        }
    }
}

然后你的測試減少到兩行

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

如果你想在便攜式類庫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());

如果需要,您可以檢查具有此特殊屬性的屬性數。

您可以使用Attribute.IsDefined方法

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

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

您可以提供您專門尋找的屬性,或者您可以使用反射迭代所有屬性,例如:

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

現在可以使用新的C#特性nameof()以類型安全的方式在沒有表達式樹和擴展方法的情況下完成此操作,如下所示:

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

nameof()在C#6中引入

這是一個很老的問題,但我用過

我的方法有這個參數,但它可以構建:

Expression<Func<TModel, TValue>> expression

然后在這個方法中:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM