我有一个compex对象
class A
{
int Field1;
int field2;
property ClassB ClassB;
property classC classC;
etc etc....
}
Run Code Online (Sandbox Code Playgroud)
我想用反射打印完整的对象图.有什么好的代码吗?
一种极简主义的替代方案,能够以可读格式显示复杂对象:
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<object>().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 + "???";
}
}
Run Code Online (Sandbox Code Playgroud)
因为它编译,我有点像我的.我已经将它实现为一系列扩展方法和静态内容,因此将它放在项目中的某个静态类中,一旦包含包含静态类的命名空间,扩展方法将立即可用.以下是您使用它的方式:
myObject.PrintGraph();
Run Code Online (Sandbox Code Playgroud)
它将递归地一直向下遍历图形,直到它找到可以转换为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
Run Code Online (Sandbox Code Playgroud)
但它只打印公共属性.
这是PrintGraph方法:
/// <summary>
/// Prints the graph of this object using Debug.Print.
/// </summary>
/// <param name="o">This object.</param>
/// <param name="prefix">Optional text to prepend to all lines printed by this method.
/// </param>
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);
}
Run Code Online (Sandbox Code Playgroud)
以下是使其运行所需的基础设施:
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)};
/// <summary>
/// Returns true if this Type matches any of a set of Types.
/// </summary>
/// <param name="type">This type.</param>
/// <param name="types">The Types to compare this Type to.</param>
public static bool In(this Type type, params Type[] types)
{
foreach (Type t in types) if (t.IsAssignableFrom(type)) return true; return false;
}
/// <summary>
/// Returns true if this Type is one of the types accepted by Convert.ToString()
/// (other than object).
/// </summary>
public static bool IsConvertible(this Type t) { return t.In(ConvertibleTypes); }
/// <summary>
/// Gets whether this type is enumerable.
/// </summary>
public static bool IsEnumerable(this Type t)
{
return typeof(IEnumerable).IsAssignableFrom(t);
}
/// <summary>
/// Returns true if this property's getter is public, has no arguments, and has no
/// generic type parameters.
/// </summary>
public static bool SimpleGetter(this PropertyInfo info)
{
MethodInfo method = info.GetGetMethod(false);
return method != null && method.GetParameters().Length == 0 &&
method.GetGenericArguments().Length == 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8854 次 |
| 最近记录: |