2012-10-25 185 views
3

我正在構建我自己的屬性庫,並且我想檢查屬性級別是否有屬性。目前,我有這個方法非常有效:用lambda表達式替換字符串作爲屬性名稱

public static bool HasPropertyAttribute<T>(this object instance, string propertyName) 
    { 
     return Attribute.GetCustomAttributes(instance.GetType().GetProperty(propertyName), typeof(T), true).Any(); 
    } 

現在,我尋找到解決方案,讓我渡過lambda表達式而不是字符串propertyName的。有一種優雅的方式做到這一點不增加這種方法成爲兩個通用類型的依賴,又名:

HasPropertyAttribute<T, TProperty>(...). 
+0

http://blog.slaks.net/2010/12/partial型推理功能於net.html – SLaks

回答

6

您可以使用Lambda表達式來解決編譯時的性能基準。 (從Retrieving Property name from lambda expression修改後的代碼)

public PropertyInfo GetPropertyInfo<TProperty>(
    Expression<Func<TProperty>> propertyLambda) 
{ 
    MemberExpression member = propertyLambda.Body as MemberExpression; 
    if (member == null) 
     throw new ArgumentException(string.Format(
      "Expression '{0}' refers to a method, not a property.", 
      propertyLambda.ToString())); 

    PropertyInfo propInfo = member.Member as PropertyInfo; 
    if (propInfo == null) 
     throw new ArgumentException(string.Format(
      "Expression '{0}' refers to a field, not a property.", 
      propertyLambda.ToString())); 

    return propInfo; 
} 

你並不需要使用它作爲一個擴展方法(但如果你要適應它,你可以,但有一個源對象實例是沒有必要的,除了寫行)

public class Test 
{ 
    public string Prop { get; set; } 
} 

Test t = new Test(); 
PropertyInfo propInfo = GetPropertyInfo(() => t.Prop); 
Console.WriteLine(propInfo.Name + " -> " + propInfo.PropertyType); //Prop -> System.String 

編輯:如果你想有一些不錯的語法和必須避免現有參考類型的對象,你可以這樣做:

public static class TypedReflection<TSource> 
{ 
    public static PropertyInfo GetPropertyInfo<TProperty>(
     Expression<Func<TSource, TProperty>> propertyLambda) 
    { 
     MemberExpression member = propertyLambda.Body as MemberExpression; 
     if (member == null) 
      throw new ArgumentException(string.Format(
       "Expression '{0}' refers to a method, not a property.", 
       propertyLambda.ToString())); 

     PropertyInfo propInfo = member.Member as PropertyInfo; 
     if (propInfo == null) 
      throw new ArgumentException(string.Format(
       "Expression '{0}' refers to a field, not a property.", 
       propertyLambda.ToString())); 

     return propInfo; 
    } 
} 

,並調用它像:

PropertyInfo propInfo = TypedReflection<Test>.GetPropertyInfo(o => o.Prop); 

在這一點上,它很容易增加額外的類型化思考方法(get方法,字段等)

編輯:它仍然是八九不離十兩個泛型類型的依賴,但它通過類型推斷隱藏起來。我更喜歡第二個例子;至少需要指定聲明類類型(因爲您想要類型安全),但不需要對象實例。它也有好處(我懷疑你是在這之後的),如果你重命名屬性,它會傳播到這個代碼獲得PropertyInfo

0

我選擇了這個解決方案,至少所有的代碼:

public static bool HasPropertyAttribute<T, TProperty>(this T instance, Expression<Func<T, TProperty>> propertySelector, Type attribute) 
    { 
     return Attribute.GetCustomAttributes(instance.GetType().GetProperty((propertySelector.Body as MemberExpression).Member.Name), attribute, true).Any(); 
    } 

被調用是這樣的:

var cc = new CustomClass(); 
cc.HasPropertyAttribute(x => x.Name, typeof(NullableAttribute))