调试用对象输出

编写程序跟踪输出时,有时候需要输出某个对象所有字段和属性的值,类似于Watch。如果只有一个两个类的对象,事情并不麻烦,但是如果有很多类的对象,那么单独写就很费时。鉴于此,我写了一个通用的对象转储输出类,用于针对绝大多数对象进行转储为字符串形式。

 

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Reflection;

namespace Abacl.Library.Diagnostics
{
    [Flags]
    
public enum ObjectDumpOptions
    {
        Fields 
= 0x00000001,
        Properties 
= 0x00000002,

        NonPublic 
= 0x00000010,
        Static 
= 0x00000020,

        Recurisive 
= 0x00001000,
        ExpandArray 
= 0x00002000,

        WithType 
= 0x00010000,
        UsingFullTypeName 
= 0x00040000,
        UsingTypeKeywords 
= 0x00080000,
        WithName 
= 0x00100000,

        SingleLine 
= 0x01000000,
        NullIsNull 
= 0x02000000,

        Default 
= Fields | Recurisive | UsingTypeKeywords | WithName | WithType | ExpandArray,
        DefaultBrief 
= Fields | Recurisive | UsingTypeKeywords | WithType | WithName | SingleLine,
        DefaultBriefMultiLines 
= Fields | Recurisive | UsingTypeKeywords | WithType| WithName
    }

    
public static class TextDump
    {
        
public static string DumpObject(object obj, ObjectDumpOptions options)
        {
            
return DumpObject(obj, options, 0);
        }

        
public static string DumpObject(object obj, ObjectDumpOptions options, int indent)
        {
            StringBuilder sb 
= new StringBuilder();

            
if (obj == null)
            {
                
if ((options & ObjectDumpOptions.NullIsNull) != 0)
                {
                    
return null;
                }
                
else
                {
                    
return "<null>";
                }
            }
            
else
            {
                Type type 
= obj.GetType();

                
if ((options & ObjectDumpOptions.WithType) != 0)
                {
                    sb.Append(
'(');

                    
if ((options & ObjectDumpOptions.UsingTypeKeywords) != 0)
                    {
                        
if (type.IsArray)
                        {
                            sb.Append(
"array ");
                        }

                        
if (type.IsClass && type != typeof(string))
                        {
                            
if (type.IsSubclassOf(typeof(Delegate)))
                            {
                                sb.Append(
"delegate ");
                            }
                            
else if (type.IsValueType)
                            {
                                sb.Append(
"struct ");
                            }
                            
else
                            {
                                sb.Append(
"class ");
                            }
                        }

                        
if (type.IsAnsiClass || type.IsUnicodeClass || type.IsAutoClass)
                        {
                            
if (type.IsValueType && !type.IsPrimitive && !type.IsEnum)
                            {
                                sb.Append(
"struct ");
                            }
                        }

                        
if (type.IsEnum)
                        {
                            sb.Append(
"enum ");
                        }

                        
if (type.IsInterface)
                        {
                            sb.Append(
"interface ");
                        }
                    }

                    
if ((options & ObjectDumpOptions.UsingFullTypeName) != 0)
                    {
                        sb.Append(ConvertToTypeKeywords(type, 
true));
                    }
                    
else
                    {
                        sb.Append(ConvertToTypeKeywords(type, 
false));
                    }

                    sb.Append(
')');
                }

                
if (type.IsPrimitive)
                {
                    
if (type == typeof(char))
                    {
                        sb.Append(
'\'' + obj.ToString() + '\'');
                    }
                    
else
                    {
                        sb.Append(obj.ToString());
                    }
                }
                
else if (type.IsEnum)
                {
                    sb.Append(obj.ToString());
                }
                
else if (type == typeof(string))
                {
                    sb.Append(
'"' + obj.ToString() + '"');
                }
                
else if (type.IsSubclassOf(typeof(Delegate)))
                {
                    Delegate d 
= (Delegate)obj;

                    
if ((options & ObjectDumpOptions.UsingFullTypeName) != 0)
                    {
                        sb.Append(d.Method.DeclaringType.FullName 
+ '.' + d.Method.Name);
                    }
                    
else
                    {
                        sb.Append(d.Method.DeclaringType.Name 
+ '.' + d.Method.Name);
                    }
                }
                
else if (type.IsArray)
                {
                    Array array 
= (Array)obj;

                    
if ((options & ObjectDumpOptions.ExpandArray) != 0)
                    {
                        sb.Append(
'[');
                        
if ((options & ObjectDumpOptions.SingleLine) == 0)
                        {
                            Indent(
ref indent, sb);
                        }

                        
bool first = true;

                        
for (int i = array.GetLowerBound(0); i < array.GetUpperBound(0); ++i)
                        {
                            
if (!first)
                            {
                                sb.Append(
"");

                                
if ((options & ObjectDumpOptions.SingleLine) == 0)
                                {
                                    NewLine(indent, sb);
                                }
                            }

                            sb.AppendFormat(
"array[{0}] = ", i);
                            sb.Append(DumpObject(array.GetValue(i), GetRecurisiveOptions(options), indent));
                            first 
= false;
                        }

                        
if ((options & ObjectDumpOptions.SingleLine) == 0)
                        {
                            Unindent(
ref indent, sb);
                        }
                        sb.Append(
']');
                    }
                    
else
                    {
                        sb.AppendFormat(
"<{0} elements>", array.Length);
                    }
                }
                
else
                {
                    sb.Append(
'[');
                    
if ((options & ObjectDumpOptions.SingleLine) == 0)
                    {
                        Indent(
ref indent, sb);
                    }

                    
bool isFirst = true;

                    
if ((options & ObjectDumpOptions.Fields) != 0)
                    {
                        
foreach (FieldInfo field in type.GetFields(GetBindingFlags(options)))
                        {
                            
if (!isFirst)
                            {
                                sb.Append(
"");

                                
if ((options & ObjectDumpOptions.SingleLine) == 0)
                                {
                                    NewLine(indent, sb);
                                }
                            }

                            
if ((options & ObjectDumpOptions.WithName) != 0)
                            {
                                sb.Append(field.Name);
                                sb.Append(
" = ");
                            }

                            sb.Append(DumpObject(field.GetValue(obj), GetRecurisiveOptions(options), indent));
                            isFirst 
= false;
                        }
                    }

                    
if ((options & ObjectDumpOptions.Properties) != 0)
                    {
                        
foreach (PropertyInfo property in type.GetProperties(GetBindingFlags(options)))
                        {
                            
if (!isFirst)
                            {
                                sb.Append(
"");

                                
if ((options & ObjectDumpOptions.SingleLine) == 0)
                                {
                                    NewLine(indent, sb);
                                }
                            }

                            
if ((options & ObjectDumpOptions.WithName) != 0)
                            {
                                sb.Append(property.Name);
                                sb.Append(
" = ");
                            }

                            ParameterInfo[] parameters 
= property.GetIndexParameters();

                            
if (parameters == null || parameters.Length == 0)
                            {
                                sb.Append(DumpObject(property.GetValue(obj, 
null), GetRecurisiveOptions(options), indent));
                            }
                            
else
                            {
                                sb.Append(
"<>");
                            }

                            isFirst 
= false;
                        }
                    }
                    
if ((options & ObjectDumpOptions.SingleLine) == 0)
                    {
                        Unindent(
ref indent, sb);
                    }
                    sb.Append(
']');
                }

                
return sb.ToString();
            }
        }

        
public static string DumpMethod(ObjectDumpOptions options, string methodName, object result, params object[] args)
        {
            StringBuilder sb 
= new StringBuilder();
            
int indent = 0;

            sb.Append(methodName);
            sb.Append(
'(');

            
if ((options & ObjectDumpOptions.SingleLine) == 0 && args.Length != 0)
            {
                Indent(
ref indent, sb);
            }

            
bool isFirst = true;

            
foreach (object arg in args)
            {
                
if (!isFirst)
                {
                    sb.Append(
"");

                    
if ((options & ObjectDumpOptions.SingleLine) == 0)
                    {
                        NewLine(indent, sb);
                    }
                }

                sb.Append(DumpObject(arg, options, indent));
                isFirst 
= false;
            }

            
if ((options & ObjectDumpOptions.SingleLine) == 0 && args.Length != 0)
            {
                Unindent(
ref indent, sb);
            }

            sb.Append(
") = ");
            sb.Append(DumpObject(result, options, indent));

            
return sb.ToString();
        }

        
private static string ConvertToTypeKeywords(Type type, bool fullName)
        {
            Debug.Assert(type 
!= null);

            
if (type == typeof(bool))
            {
                
return "bool";
            }

            
if (type == typeof(char))
            {
                
return "char";
            }

            
if (type == typeof(byte))
            {
                
return "byte";
            }

            
if (type == typeof(sbyte))
            {
                
return "sbyte";
            }

            
if (type == typeof(short))
            {
                
return "short";
            }

            
if (type == typeof(ushort))
            {
                
return "ushort";
            }

            
if (type == typeof(int))
            {
                
return "int";
            }

            
if (type == typeof(uint))
            {
                
return "uint";
            }

            
if (type == typeof(long))
            {
                
return "long";
            }

            
if (type == typeof(ulong))
            {
                
return "ulong";
            }

            
if (type == typeof(float))
            {
                
return "float";
            }

            
if (type == typeof(double))
            {
                
return "double";
            }

            
if (type == typeof(decimal))
            {
                
return "decimal";
            }

            
if (type == typeof(string))
            {
                
return "string";
            }

            
if (type == typeof(Nullable))
            {
                
return ConvertToTypeKeywords(Nullable.GetUnderlyingType(type), fullName) + "?";
            }

            
if (fullName)
            {
                
return type.FullName;
            }
            
else
            {
                
return type.Name;
            }
        }

        
private static BindingFlags GetBindingFlags(ObjectDumpOptions options)
        {
            BindingFlags flags 
= BindingFlags.Public;

            
if ((options & ObjectDumpOptions.NonPublic) != 0)
            {
                flags 
|= BindingFlags.NonPublic;
            }

            
if ((options & ObjectDumpOptions.Static) != 0)
            {
                flags 
|= BindingFlags.Static;
            }
            
else
            {
                flags 
|= BindingFlags.Instance;
            }

            
return flags;
        }

        
private static ObjectDumpOptions GetRecurisiveOptions(ObjectDumpOptions options)
        {
            
if ((options & ObjectDumpOptions.Recurisive) == 0)
            {
                options 
&= ~ObjectDumpOptions.Fields;
                options 
&= ~ObjectDumpOptions.Properties;
                options 
&= ~ObjectDumpOptions.ExpandArray;
            }

            
return options;
        }

        
private static void Indent(ref int indent, StringBuilder sb)
        {
            
++indent;
            NewLine(indent, sb);
        }

        
private static void Unindent(ref int indent, StringBuilder sb)
        {
            
--indent;
            NewLine(indent, sb);
        }

        
private static void NewLine(int indent, StringBuilder sb)
        {
            sb.Append(Environment.NewLine);
            sb.Append(
new string(' ', indent * 2));
        }
    }
}

 

不同的ObjectDumpOptions指示不同的输出格式:

 

Fields:转储字段

Properties:转储属性

NonPublic:转储非公共成员(字段、属性等)

Static:转储静态成员(如选择此选项,则实例成员不会包括的输出中)

Recursive:递归转储所有内含的类型(如不包含此项,则仅转储直接成员)

ExpandArray:扩展所有数组元素(如不包含此项,则仅输出数组的元素类型以及元素数量

WithType:输出结果中包含字段或属性的类型名

UsingFullTypeName:使用完整的类型名(包含名字空间)

UsingTypeKeywords:使用C#的关键字来代替部分内置类型,如int表示Int32

WithName:输出结果中包含字段或属性的名称

SingleLine:单行输出(如果不包含此项,则会适当分行)

NullIsNull:如果输入对象是null,则转储结果为null,否则转储结果为字符串“<null>”

Default,DefaultBrief,DefaultBriefMultiLines:包括一些常用的选项。

 

DumpObject函数用于转储一个对象,DumpMethod函数用于转储一个方法的调用。对于下面这个程序:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
    public class Test
    {
        
private int m_field;

        
public int Property
        {
            
get
            {
                
return m_field;
            }
        }

        
public Test(int value)
        {
            m_field 
= value;
        }
    }

    
class Program
    {
        
static void Main(string[] args)
        {
            Test test 
= new Test(100);
            
string dump = TextDump.DumpObject(test, ObjectDumpOptions.Fields | ObjectDumpOptions.Properties | ObjectDumpOptions.NonPublic | ObjectDumpOptions.Recurisive | ObjectDumpOptions.ExpandArray | ObjectDumpOptions.WithType | ObjectDumpOptions.WithName | ObjectDumpOptions.NullIsNull);

            Console.WriteLine(dump);
        }
    }

 

输出的结果是:

 

(Test)[
  m_field = (int)100,
  Property = (int)100
]

 

 

转载于:https://www.cnblogs.com/xlshcn/archive/2009/04/06/objectdump.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值