2013-12-10 58 views
6

我有一個數據庫對象類,做了一堆繁重工作。然後,我擴展該對象並構建表示要修改的實際對象和字段的類。它基本上是這樣的:C#如何獲取正在設置的財產的名稱

public class MyObject : DatabaseObject 
{ 
    public string FieldX 
    { 
     get { return GetValue<string>("FieldX"); } 
     set { SetValue<string>("FieldX", value); } 
    } 

    public int FieldY 
    { 
     get { return GetValue<int>("FieldY"); } 
     set { SetValue<int>("FieldY", value); } 
    } 
} 

public class DatabaseObject 
{ 
    public T GetValue<T>(string FieldName) 
    { 
     // Code that actually gets the right value 
    } 

    public void SetValue<T>(string FieldName, T value) 
    { 
     // Code that actually sets the value in the right place 
    } 
} 

這樣,我可以在稍後實例化MyObject並通過代碼開始設置屬性。這個想法是產生更簡單,更易維護的代碼。

它在實踐中效果很好。不過,我注意到MyObject的代碼非常重複。例如,使用FieldX,我最終在get/set中指定了「string」類型,並且還必須在get/set中指定屬性名稱「FieldX」。

我想知道是否有辦法進一步簡化代碼以減少重複。

我知道我可以使用反射:

MethodBase.GetCurrentMethod().Name.Substring(4) 

...裏面的get/set調用來獲得屬性名,我可以用gettype()做集時得到的值的類型,但理想情況下,我希望從基本GetValue/SetValue方法中獲取原始屬性名稱(理想情況下不需要解析堆棧跟蹤)。

理想情況下,我正在尋找這樣的事情:

public string FieldX 
    { 
     get { return GetValue(); } 
     set { SetValue(value); } 
    } 

    public int FieldY 
    { 
     get { return GetValue(); } 
     set { SetValue(value); } 
    } 

有什麼想法?

回答

3

這比您尋找的時間稍長一些,但也可以使用(使用強類型 lambda表達式)。

public class MyObject : DatabaseObject 
{ 
    public string FieldX 
    { 
     get { return GetValue(() => FieldX); } 
     set { SetValue(() => FieldX, value); } 
    } 

    public int FieldY 
    { 
     get { return GetValue(() => FieldY); } 
     set { SetValue(() => FieldY, value); } 
    } 
} 

public class DatabaseObject 
{ 
    public T GetValue<T>(Expression<Func<T>> field) 
    { 
     string fieldName = GetFieldName(field); 
     // Code that actually gets the right value 
    } 

    public void SetValue<T>(Expression<Func<T>> field, T value) 
    { 
     string fieldName = GetFieldName(field); 
     // Code that actually sets the value in the right place 
    } 

    private static string GetFieldName<T>(Expression<Func<T>> field) 
    { 
     return ((MemberExpression)field.Body).Member.Name; 
    } 
} 
7

C#5.0通過在默認參數上使用[CallerMemberName]屬性來支持此操作。事情是這樣的:

public static object GetValue([CallerMemberName] string caller = "") 
{ 
    Trace.WriteLine("Called by: " + caller); 
    return null; 
} 

,並會使用這樣的:

public string FieldX 
{ 
    get { return (string)GetValue(); } 
} 

這個工程由編譯器自動提供的GetValue根據來電者的名稱的參數。

您可以瞭解關於此功能的更多信息in MSDN

您或許可以製造GetValue通用名稱,因此可以在您的屬性中使用它,如GetValue<string>()

+0

我想我不能標記兩個答案是正確的。我認爲上面的C#5.0答案可能是正確的長期方法,但不幸的是,項目要求限制了我今天的使用,所以我必須回到下面的答案。 – jhilgeman