2008-12-23 167 views
6

我知道我可以擁有一個屬性,但這比我想去的工作要多...而且不夠通用。如何從C#中的屬性獲取房產的名稱(2.0)

我要像做

class Whotsit 
{ 
    private string testProp = "thingy"; 

    public string TestProp 
    { 
     get { return testProp; } 
     set { testProp = value; } 
    } 

} 

... 

Whotsit whotsit = new Whotsit(); 
string value = GetName(whotsit.TestProp); //precise syntax up for grabs.. 

,我所期待的價值等於「TestProp」

,但我不能爲我的生活找到合適的反射的方法來寫GetName方法...

編輯:我爲什麼要這樣做?我有一個類來存儲從「名稱」,「值」表讀取的設置。這是通過基於反思的廣義方法來填充的。我很喜歡寫反...

/// <summary> 
/// Populates an object from a datatable where the rows have columns called NameField and ValueField. 
/// If the property with the 'name' exists, and is not read-only, it is populated from the 
/// valueField. Any other columns in the dataTable are ignored. If there is no property called 
/// nameField it is ignored. Any properties of the object not found in the data table retain their 
/// original values. 
/// </summary> 
/// <typeparam name="T">Type of the object to be populated.</typeparam> 
/// <param name="toBePopulated">The object to be populated</param> 
/// <param name="dataTable">'name, 'value' Data table to populate the object from.</param> 
/// <param name="nameField">Field name of the 'name' field'.</param> 
/// <param name="valueField">Field name of the 'value' field.</param> 
/// <param name="options">Setting to control conversions - e.g. nulls as empty strings.</param> 

public static void PopulateFromNameValueDataTable<T> 
     (T toBePopulated, System.Data.DataTable dataTable, string nameField, string valueField, PopulateOptions options) 
    { 
     Type type = typeof(T); 
     bool nullStringsAsEmptyString = options == PopulateOptions.NullStringsAsEmptyString; 

     foreach (DataRow dataRow in dataTable.Rows) 
     { 
      string name = dataRow[nameField].ToString(); 
      System.Reflection.PropertyInfo property = type.GetProperty(name); 
      object value = dataRow[valueField]; 

      if (property != null) 
      { 
       Type propertyType = property.PropertyType; 
       if (nullStringsAsEmptyString && (propertyType == typeof(String))) 
       { 
        value = TypeHelper.EmptyStringIfNull(value); 
       } 
       else 
       { 
        value = TypeHelper.DefaultIfNull(value, propertyType); 
       } 

       property.SetValue(toBePopulated, System.Convert.ChangeType(value, propertyType), null); 
      } 
     } 
    } 

進一步編輯:我只是在代碼中,有Whotsit的實例,我想要得到的「TestProp」屬性的文本字符串。這似乎有點怪異我知道,我可以只使用文字「TestProp」 - 或者在我的類的情況下datatable函數我會在PropertyInfos的foreach循環。我只是好奇...

原始代碼有字符串常量,我發現笨拙。

+0

你可能在這裏回答http://stackoverflow.com/a/1225702/661933 – nawfal 2013-04-27 14:51:30

回答

6

不,這沒有什麼可做的。表達式whotsit.TestProp將評估財產。你想要的是傳說中的「infoof」運營商:

// I wish... 
MemberInfo member = infoof(whotsit.TestProp); 

正因爲如此,你只能使用反射來獲取由名稱的屬性 - 不是從代碼。 (或者獲得所有屬性,當然它仍然沒有幫你的樣品,雖然。)

一種替代方法是使用表達式樹:

Expression<Func<string>> =() => whotsit.TestProp; 

然後檢查表達式樹來獲得財產。

如果這些都沒有幫助,也許您可​​以告訴我們更多關於您爲什麼要使用此功能的信息?

-1

GetProperties on the Type class會給你這種類型的屬性列表。

Type t = whotsit.GetType(); 
PropertyInfo[] pis = t.GetProperties(); 
+0

真實的,但沒有太大的用處,因爲我想要什麼做,因爲它是我後面的名稱字符串... – kpollock 2008-12-23 13:01:14

0

你想要做的是不可能的。使用反射,您可以:

  • 從它的字符串名稱獲取屬性,字段或方法的詳細信息。
  • 獲取給定類型的所有屬性,字段或方法的列表。

您的GetName方法在調用時傳遞一個字符串。 GetMethod將知道該字符串,但不保留源屬性元數據。

出於興趣,你爲什麼要這麼做?

0

我不認爲這是可能的,要做到這一點的唯一方法是遍歷屬性:

class TestClass 
{ 
    private string _field; 

    public string MyProperty 
    { 
     get { return _field; } 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     TestClass test = new TestClass(); 
     PropertyInfo[] info = test.GetType().GetProperties(); 
     foreach(PropertyInfo i in info) 
      Console.WriteLine(i.Name); 
     Console.Read(); 
    } 
} 
+0

它仍然不會給我能力從它的一個實例獲取屬性的名稱。 – kpollock 2008-12-23 13:03:29

3

這是可能的(無反射),但只有與最新的C#3.0

快速&非常非常髒

class Program 
{ 
    static void Main() 
    { 
     string propertyName = GetName(() => AppDomain.CurrentDomain); 
     Console.WriteLine(propertyName); // prints "CurrentDomain" 
     Console.ReadLine(); 
    } 

    public static string GetName(Expression<Func<object>> property) 
    { 
     return property.Body.ToString().Split('.').Last(); 
    } 
} 

更新:我剛剛意識到Jon Skeet(有人驚訝? :)已經涵蓋了這種可能性,但我會在這裏保留我的答案,以防某人對某個例子感興趣。

+0

還需要.NET 3.5(OP狀態2.0) – 2008-12-23 13:24:09

0

Kpollack,您在前面的評論說:

仍然不會給我從它的一個實例獲取屬性的名稱的能力。

這使我相信你有某種方式有一個屬性的參考。你是如何得到這個參考的?它的類型是什麼?你能提供一個代碼示例嗎?如果它是一個PropertyInfo對象,那麼你已經擁有了你需要的東西;因爲這看起來並不是這樣,所以我們正在處理其他事情,並且我會很感興趣地看到必須與之合作。

P.S.原諒我看起來很呆板:現在很早,我沒有足夠的咖啡,我沒有我的IDE在我面前。 : -/

0

僅供參考,我試圖序列化它,看偶然是否包含屬性名稱,但沒有運氣。

不工作的代碼如下:

Whotsit w = new Whotsit(); 
XmlSerializer xs = new XmlSerializer(w.TestProp.GetType()); 
TextWriter sw = new StreamWriter(@"c:\TestProp.xml"); 
xs.Serialize(sw, w.TestProp); 
sw.Close();