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