列出对象属性,如Visual Studio立即窗口

我在会话中存储了几个类。 我希望能够在跟踪查看器中查看我的类属性的值。 默认情况下,我只输入类型名称MyNamespace.MyClass。 我想知道我是否覆盖.ToString()方法并使用reflection来遍历所有属性并构造一个类似的字符串…它会做的伎俩但只是想看看是否有任何东西(特别是立即窗口具有此function)它执行相同的操作…即列出跟踪中的类属性值而不仅仅是类的名称。

我相信这会有所帮助: C#object dumper

你可以试试这样的东西:

static void Dump(object o, TextWriter output) { if (o == null) { output.WriteLine("null"); return; } var properties = from prop in o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public) where prop.CanRead && !prop.GetIndexParameters().Any() // exclude indexed properties to keep things simple select new { prop.Name, Value = prop.GetValue(o, null) }; output.WriteLine(o.ToString()); foreach (var prop in properties) { output.WriteLine( "\t{0}: {1}", prop.Name, (prop.Value ?? "null").ToString()); } } 

当然,由于reflection效果不是很有效……更好的解决方案是为每种特定类型动态生成和缓存转储器方法。


编辑:这是一个改进的解决方案,它使用Linq表达式为每种类型生成一个专门的转储器方法。 稍微复杂一些;)

 static class Dumper { private readonly static Dictionary> _dumpActions = new Dictionary>(); private static Action CreateDumper(Type type) { MethodInfo writeLine1Obj = typeof(TextWriter).GetMethod("WriteLine", new[] { typeof(object) }); MethodInfo writeLine1String2Obj = typeof(TextWriter).GetMethod("WriteLine", new[] { typeof(string), typeof(object), typeof(object) }); ParameterExpression objParam = Expression.Parameter(typeof(object), "o"); ParameterExpression outputParam = Expression.Parameter(typeof(TextWriter), "output"); ParameterExpression objVariable = Expression.Variable(type, "o2"); LabelTarget returnTarget = Expression.Label(); List bodyExpressions = new List(); bodyExpressions.Add( // o2 = ()o Expression.Assign(objVariable, Expression.Convert(objParam, type))); bodyExpressions.Add( // output.WriteLine(o) Expression.Call(outputParam, writeLine1Obj, objParam)); var properties = from prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public) where prop.CanRead && !prop.GetIndexParameters().Any() // exclude indexed properties to keep things simple select prop; foreach (var prop in properties) { bool isNullable = !prop.PropertyType.IsValueType || prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>); // (object)o2. (cast to object to be passed to WriteLine) Expression propValue = Expression.Convert( Expression.Property(objVariable, prop), typeof(object)); if (isNullable) { // ( ?? "null") propValue = Expression.Coalesce( propValue, Expression.Constant("null", typeof(object))); } bodyExpressions.Add( // output.WriteLine("\t{0}: {1}", "", ) Expression.Call( outputParam, writeLine1String2Obj, Expression.Constant("\t{0}: {1}", typeof(string)), Expression.Constant(prop.Name, typeof(string)), propValue)); } bodyExpressions.Add(Expression.Label(returnTarget)); Expression> dumperExpr = Expression.Lambda>( Expression.Block(new[] { objVariable }, bodyExpressions), objParam, outputParam); return dumperExpr.Compile(); } public static void Dump(object o, TextWriter output) { if (o == null) { output.WriteLine("null"); } Type type = o.GetType(); Action dumpAction; if (!_dumpActions.TryGetValue(type, out dumpAction)) { dumpAction = CreateDumper(type); _dumpActions[type] = dumpAction; } dumpAction(o, output); } } 

用法:

 Dumper.Dump(myObject, Console.Out); 

这是我使用的代码。 我发现它非常有用,而且几乎是即时的。 代码使用的是Newtonsoft JSON转换器。

  [System.Obsolete("ObjectDump should not be included in production code.")] public static void Dump(this object value) { try { System.Diagnostics.Trace.WriteLine(JsonConvert.SerializeObject(value, Formatting.Indented)); } catch (Exception exception) { System.Diagnostics.Trace.WriteLine("Object could not be formatted. Does it include any interfaces? Exception Message: " + exception.Message); } } 

将其添加到公共库,引用它并将其添加到using子句。 可以通过键入YourObject.Dump()在直接窗口中使用(与在linqpad中完全相同)。

包含接口的类必须以不同方式处理,因为这只是一个JSON转换器。 包含我使用的接口实现的类的解决方法是删除默认的空构造函数,并使用接口的特定实例实现构造函数。

我发现JSON是一种非常容易阅读的格式,并认为这种小方法非常适合调试。