2010-01-12 219 views
115

給定一個類中的屬性和屬性 - 確定它是否包含給定屬性的最快方法是什麼?例如:檢查屬性是否具有屬性

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

確定例如它具有「IsIdentity」屬性的最快方法是什麼?

回答

209

沒有快速的方法來檢索屬性。但是,代碼應該是這樣的(信貸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 
} 
+52

如果您只需檢查屬性的存在性,並且不從中檢索任何信息,那麼使用Attribute.IsDefined將消除一行代碼和醜陋的數組/鑄造。 – Aaronaught 2010-01-12 18:42:50

38

如果您使用的是.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; 
    } 
} 
+6

僅供參考有人問你的答案。 http://stackoverflow.com/questions/4158996/why-are-expression-trees-safer-than-reflection – Greg 2010-11-11 20:35:53

11

您可以使用一個共同的(通用)方法在給定的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; 
      } 
5

讀取屬性更新和/或增強@Hans帕桑特我想答案將該屬性的檢索分離爲擴展方法。這已在方法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)); 
5

如果你正在嘗試做的去除討厭魔法字符串的好處是,在便攜類圖書館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()); 

然後,您可以檢查,如果你需要有這個特殊的財產屬性的個數。

1

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

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

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

這可以現在可以使用新的C#特性nameof()這樣的類型安全方式來完成表達式樹和擴展方法:

Attribute.IsDefined(typeof(YourClass).GetProperty(nameof(YourClass.Id)), typeof(IsIdentity)); 
相關問題