使用C#和reflection打印完整对象图

我有一个compex对象

class A { int Field1; int field2; property ClassB ClassB; property classC classC; etc etc.... } 

我想用reflection打印完整的对象图。 有什么好的代码吗?

几年前我做了一些调试工作。 它是一个递归函数,可以打印所有属性和子对象。 您的打印方式取决于您。 只需将您想要的代码放在print方法中即可。 它不是“防弹”,但效果很好:

 private static void displayObject(object myObject, bool displaySubObject, Type objectType) { print(objectType.FullName); if (myObject == null) {   print(STR_Null); } else {  //check for collection  if (objectType.GetInterface("IEnumerable") != null) {   int itemNb = 0;   foreach (object item in (IEnumerable)myObject) {   displayObject(item, displaySubObject, item.GetType);    itemNb += 1;   }  }  else {   ArrayList al = new ArrayList();   Reflection.PropertyInfo pi = default(Reflection.PropertyInfo);   Reflection.MemberInfo[] members = objectType.GetMembers();   foreach (Reflection.MemberInfo mi in objectType.GetMembers()) {   if ((mi.MemberType & Reflection.MemberTypes.Constructor) != 0){//ignore constructor}    else if (object.ReferenceEquals(mi.DeclaringType, typeof(object))) {//ignore inherited}    else if (!al.Contains(mi.Name) & (mi.MemberType & Reflection.MemberTypes.Property) != 0) {    al.Add(mi.Name);     pi = (Reflection.PropertyInfo)mi;     if (!(displaySubObject) || (pi.PropertyType.IsValueType || pi.PropertyType.Equals(typeof(string)))) {      print(pi, myObject);     }     else {      //display sub objects      displayObject(pi.GetValue(myObject, null), displaySubObject, i.PropertyType);     }    }   }  } } } 

希望能帮助到你

一种极简主义的替代方案,能够以可读格式显示复杂对象:

 public static string Dump(object o, string name = "", int depth = 3) { try { var leafprefix = (string.IsNullOrWhiteSpace(name) ? name : name + " = "); if (null == o) return leafprefix + "null"; var t = o.GetType(); if (depth-- < 1 || t == typeof (string) || t.IsValueType) return leafprefix + o; var sb = new StringBuilder(); var enumerable = o as IEnumerable; if (enumerable != null) { name = (name??"").TrimEnd('[', ']') + '['; var elements = enumerable.Cast().Select(e => Dump(e, "", depth)).ToList(); var arrayInOneLine = elements.Count + "] = {" + string.Join(",", elements) + '}'; if (!arrayInOneLine.Contains(Environment.NewLine)) // Single line? return name + arrayInOneLine; var i = 0; foreach (var element in elements) { var lineheader = name + i++ + ']'; sb.Append(lineheader).AppendLine(element.Replace(Environment.NewLine, Environment.NewLine+lineheader)); } return sb.ToString(); } foreach (var f in t.GetFields()) sb.AppendLine(Dump(f.GetValue(o), name + '.' + f.Name, depth)); foreach (var p in t.GetProperties()) sb.AppendLine(Dump(p.GetValue(o, null), name + '.' + p.Name, depth)); if (sb.Length == 0) return leafprefix + o; return sb.ToString().TrimEnd(); } catch { return name + "???"; } } 

因为它编译,我有点像我的更好。 我已经将它实现为一系列扩展方法和静态内容,因此将它放在项目中的某个静态类中,一旦包含包含静态类的命名空间,扩展方法将立即可用。 这是你如何使用它:

 myObject.PrintGraph(); 

它将以递归方式一直向下遍历图形,直到它找到可以转换为Convert.ToString()的内容,然后它将Debug.Print输出到您的即时窗口。 这是一些示例输出:

 TopLevelProperty: value //Member of myObject MyEnumerableProperty: MyItemProperty: value //A property from an object in myObject MyEnumerableProperty: MySubEnumerableProperty: MyItemProperty: value //& so on 

但它只打印公共属性。

这是PrintGraph方法:

 ///  /// Prints the graph of this object using Debug.Print. ///  /// This object. /// Optional text to prepend to all lines printed by this method. ///  public static void PrintGraph(this object o, string prefix = "") { Type t = o.GetType(); if (prefix != "") prefix = " " + prefix; foreach (PropertyInfo p in t.GetProperties()) if (p.PropertyType.IsConvertible()) Debug.Print(prefix + p.Name + ": " + Convert.ToString(p.GetValue(o, null))); else if (p.PropertyType.IsEnumerable()) foreach (object sub in (IEnumerable)p.GetValue(o, null)) PrintGraph(sub, prefix + p.Name + ": "); else if (p.SimpleGetter()) PrintGraph(p.GetValue(o, null), prefix + p.Name + ": "); if (t.IsEnumerable()) foreach (object sub in (IEnumerable)o) PrintGraph(sub); } 

以下是使其运行所需的基础设施:

 internal static Type[] ConvertibleTypes = {typeof(bool), typeof(byte), typeof(char), typeof(DateTime), typeof(decimal), typeof(double), typeof(float), typeof(int), typeof(long), typeof(sbyte), typeof(short), typeof(string), typeof(uint), typeof(ulong), typeof(ushort)}; ///  /// Returns true if this Type matches any of a set of Types. ///  /// This type. /// The Types to compare this Type to. public static bool In(this Type type, params Type[] types) { foreach (Type t in types) if (t.IsAssignableFrom(type)) return true; return false; } ///  /// Returns true if this Type is one of the types accepted by Convert.ToString() /// (other than object). ///  public static bool IsConvertible(this Type t) { return t.In(ConvertibleTypes); } ///  /// Gets whether this type is enumerable. ///  public static bool IsEnumerable(this Type t) { return typeof(IEnumerable).IsAssignableFrom(t); } ///  /// Returns true if this property's getter is public, has no arguments, and has no /// generic type parameters. ///  public static bool SimpleGetter(this PropertyInfo info) { MethodInfo method = info.GetGetMethod(false); return method != null && method.GetParameters().Length == 0 && method.GetGenericArguments().Length == 0; }