2012-02-13 44 views
1

爲了進行調試,我需要打印某些類實例的所有公共字段/屬性。我能以某種方式自動執行該操作嗎?可能在.NET 4.0中有新功能?例如,WPF DataGrid可以做類似的事情。如何在沒有迭代屬性的情況下將類的實例表示爲字符串

這可以做manualy參考這個問題Iterate through class fields and print them但我很有趣,如果我可以使用一些庫方法,而不是自己編碼?

I.e.我想將這段代碼:

 foreach (PropertyInfo prop in typeof(ServerInfo).GetProperties()) 
     { 
      result += prop.Name + " = " + prop.GetValue(si, null) + "\n"; 
     } 
     foreach (FieldInfo prop in typeof(ServerInfo).GetFields()) 
     { 
      result += prop.Name + " = " + prop.GetValue(si) + "\n"; 
     } 
     return result; 
+0

可用的代碼[here](http://stackoverflow.com/a/6745255/870604)非常簡單,爲什麼你不想使用它? – ken2k 2012-02-13 09:15:49

+0

你在答案中不喜歡什麼? – 2012-02-13 09:16:18

+0

用什麼東西代替? – 2012-02-13 09:20:30

回答

0

我不知道爲什麼你正在尋找更好的代碼。你有的代碼只是幾行,看起來很好。

如果你想修改您有任何類型的工作代碼,那麼很簡單:

string Format(object obj) 
{ 
    Type type = obj.GetType(); 

    foreach (PropertyInfo prop in type.GetProperties()) 
    { 
     result += prop.Name + " = " + prop.GetValue(obj, null) + "\n"; 
    } 
    foreach (FieldInfo field in type.GetFields()) 
    { 
     result += field.Name + " = " + field.GetValue(obj) + "\n"; 
    } 
    return result; 
} 

,可以在這個代碼進行更好的另一件事是效率:你應該使用StringBuilder,而不是連接字符串。

0

您可以覆蓋你的自定義類的ToString方法和使用的方法類似如下所述:https://stackoverflow.com/a/6745255/559144

或創建您自己的庫/幫助你把代碼在鏈接和所有您想使用的類上,只需撥打ToString覆蓋的幫助程序方法即可。

不確定你的意思是WPF Datagrid可以做到這一點,你確定你沒有談論Visual Studio Debugger DataSet可視化器嗎?

0

托馬斯引用:

User user = ... 
foreach(PropertyInfo prop in typeof(User).GetProperties()) 
{ 
    Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(user, null)); 
} 
+0

它的工作原理,但不包括字段,看起來很奇怪 – javapowered 2012-02-13 09:18:48

0

如果你的目標的屬性的簡單列表與WPF顯示,也許會使用列表框的ItemsSource與「數據綁定」到你的對象幫助。爲了從這個對象得到一個字符串列表,使用一些IValueConverter的實現,它讀取最後幾個註釋中描述的屬性,並將它們放入一個IEnumerable中。

在DataBinding中交換對象時,會立即顯示新對象。

+0

我只是想將對象轉換爲字符串。我在談論WPF,因爲WPF可以做到這一點。 – javapowered 2012-02-13 09:31:28

0

如果您確實設置了所有屬性和字段,沒有比您已經編寫的代碼更好的方法。您可以編寫一個擴展方法並將其合併到System命名空間中,這樣它就會出現在任何類型的每個實例上;我也認真考慮使用StringBuilderAppendLinestring.Format

namespace System 
{ 
    public static class MyExtensions 
    { 
    public static string Report<T>(this T instance) 
    { 
     StringBuilder sb = new StringBuilder(); 
     foreach (PropertyInfo prop in typeof(T).GetProperties()) 
     { 
     sb.AppendLine(
      string.Format("{0} = {1}", prop.Name, prop.GetValue(si, null)); 
     } 
     foreach (FieldInfo prop in typeof(T).GetFields()) 
     { 
     sb.AppendLine(
      string.Format("{0} = {1}", prop.Name, prop.GetValue(si, null)); 
     } 
     return sb.ToString(); 
    } 
    } 
} 

一旦你寫了這個,你可以簡單地做:

var instance = new ServerInfo(); 
var report = instance.Report(); 

這裏的問題是,它不處理情況下,類型的最佳表示形式實際上只是一個'ToString'調用 - 例如intstring(特別是字符串;因爲此代碼將僅輸出Length成員)。

你提到WPF數據網格 - 這是值得一提的是,不直接使用反射,而是使用了System.ComponentModel.TypeDescriptor類 - 這是可擴展的,並使用TypeConverter機制,以支持從字符串(遠好於單純依靠轉換/ ToString)。

但是,它不包含它生成的元數據中的字段;你明確想要的。

作爲最後一點,我會爭辯說,這種事情不應該在程序中使用很多;因爲這種細節水平很少很重要。那麼你的報告應該走多深的問題;對於每個成員,如果你實際上不再使用Report(在這種情況下,你必須將通用後綴綁定,或者只是使用object來代替)?但是,你有令人討厭的代碼來檢查應該下降的類型,或者只是ToString'd。如果你開始這樣做,你還需要注意不要通過交叉引用遞歸;否則你的報告方法可能會鎖定你的應用程序。

我會建議,而不是一個接口是最好的:

public interface IReportable 
{ 
    void Report(StringBuilder target); 
} 

的接口,那麼只限於你真的需要報告的類型的實現;並且您可以使用上面的擴展方法或其他類似擴展方法作爲大多數類型的默認實現。然而,至關重要的是,如果需要的話,一種類型可以提供它自己的類型。

0

你可以寫爲Type類的擴展方法:

public static class TypeExtensions 
{ 
    public static List<string> GetFieldsAndPropertiesAsString(this Type type) 
    { 
     return new List<string>(type.GetFieldsAsString().Union(type.GetPropertiesAsString())); 
    } 

    public static IEnumerable<string> GetFieldsAsString(this Type type) 
    { 
     // Modify BindingFlags to get what you want (instance only, private/public...) 
     foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) 
     { 
      yield return field.Name; 
     } 
    } 

    public static IEnumerable<string> GetPropertiesAsString(this Type type) 
    { 
     // Modify BindingFlags to get what you want (instance only, private/public...) 
     foreach (PropertyInfo prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) 
     { 
      yield return prop.Name; 
     } 
    } 
} 

使用然後調用它:

foreach (string zz in typeof(MyClass).GetFieldsAndPropertiesAsString()) 
{ 
    Console.WriteLine(zz); 
} 
相關問題