2014-03-26 55 views
0

我有一個類有一個屬性,該屬性有一個attribute,並在該屬性的get{}set{}內,我想訪問該屬性。我可以在不使用名稱的情況下獲取屬性的PropertyInfo嗎?

有沒有辦法做到這一點,而不必引用財產的名稱作爲string?這是否工作?

class MyClass 
{ 
    [DefaultValue("This is my default")] 
    public string MyProperty 
    { 
     get 
     { 
      string value = this.db.getMyProperty(); 
      if (value == null) 
      { 
       var myPropertyInfo = this.GetType().GetProperty("MyProperty"); 
       var myAttributeInfo = myPropertyInfo.GetCustomAttribute(
        typeof (DefaultValueAttribute)) as DefaultValueAttribute; 
       if (myAttributeInfo != null) 
        value = myAttributeInfo.defaultValue; 
      } 
      return value; 
     } 
    } 
} 

是什麼原因導致我這個擔心是,經過屬性的名稱是違反乾的,並使它過於容易不小心傳遞了錯誤的字符串。

如何改進此代碼以消除重複?

+0

這似乎更多的工作,而不僅僅是有一個默認參數設置的支持字段,沒有任何屬性或反射。 –

+0

我簡化了這個問題。我們從需要顯示當前值的視圖模型中填充此值,以及在用戶選擇恢復爲默認值時將使用的值。 –

回答

2

使用MethodBase.GetCurrentMethod()從方法或屬性中獲取當前引用。在你的情況下,使用Name屬性,它會返回一個字符串get_MyProperty並刪除get_部分與substring,試試這個:

[DefaultValue("This is my default")] 
public string MyProperty 
{ 
    get 
    { 
     string value = this.db.getMyProperty(); 
     if (value == null) 
     { 
      // get property name from GetCurrentMethod. 
      // use the SubString to remove the "get_" that comes from .net internals 
      var propertyName = MethodBase.GetCurrentMethod().Name.Substring(4); 

      // keep your method 
      var myPropertyInfo = this.GetType().GetProperty(propertyName); 
      var myAttributeInfo = myPropertyInfo.GetCustomAttribute(
       typeof (DefaultValueAttribute)) as DefaultValueAttribute; 
      if (myAttributeInfo != null) 
       value = myAttributeInfo.defaultValue; 
     } 
     return value; 
    } 
} 
+0

MethodBase.GetCurrentMethod()。名稱是「get_MyProperty」,而不是「MyProperty」,但如果模式與出現的模式一致,則可以剝離「get_」。 –

+1

@JeffDege:我相信這個模式應該是一致的。如果您需要其他方法,則可以改爲迭代所有屬性以找到引用「Get」方法的屬性:var getMethod = MethodBase.GetCurrentMethod(); var myPropertyInfo = this.GetType()。GetProperties()。where(pinfo => pinfo.GetGetMethod()== getMethod).First();'我不會欺騙你,它絕對不是有效的。但是,您正在生成_constant_值,因此您可能/應該可能會引入緩存機制。 –

+0

嘗試在屬性名稱上應用'.Substring(4)'來刪除這部分字符串。它來自.Net的內部,我們不能改變。 –

3

你不說這就是你正在使用的框架的版本,但如果.NET 4.5或更高版本,您可以使用CallerMemberName。下面的方法添加到MyClass

private PropertyInfo GetProperty([CallerMemberName] string name = "") 
{ 
    var myPropertyInfo = this.GetType().GetProperty(name); 
    return myPropertyInfo; 
} 

然後,在MyProperty變化

var myPropertyInfo = this.GetType().GetProperty("MyProperty");

var myPropertyInfo = this.GetProperty();

在運行時,爲GetPropertyname參數的值會提供automati爲你而做。

其實,如果你這樣做了很多(和它的總是相同的屬性),你可以簡化這個甚至更多:

private string GetDefaultValueForProperty([CallerMemberName] string name = "") 
{ 
    string defaultValue = null; 
    var myPropertyInfo = this.GetType().GetProperty(name); 
    var myAttributeInfo = myPropertyInfo.GetCustomAttribute<DefaultValueAttribute>(); 
    if (myAttributeInfo != null) 
    { 
     defaultValue = (string)myAttributeInfo.Value; 
    } 

    return defaultValue; 
} 

然後在你的屬性的代碼如下所示:

[DefaultValue("This is my default")] 
public string MyProperty 
{ 
    get 
    { 
     string value = this.db.getMyProperty(); 
     if (value == null) 
     { 
      value = GetDefaultValueForProperty(); 
     } 
     return value; 
    } 
} 
1

您可以使用擴展方法是這樣的:

public static TValue GetDefaultValue<TParent, TValue> 
    (this TParent @this, Expression<Func<TParent, TValue>> e) 
{ 
    var member = (e.Body as MemberExpression).Member; 
    var attr = member.GetCustomAttribute(typeof (DefaultValueAttribute)) 
       as DefaultValueAttribute; 

    return (TValue)attr.Value; 
} 

而現在你只需要做到這一點你[R屬性:

return GetDefaultValue(i => i.MyProperty); 

更好,編譯時檢查,並將其與重構工作太:)

擴展方法是真正的裸骨,你希望它是安全的,但這個想法應該是明確。

相關問題