Auto ToString()

I wanted to print the contents of some objects, for debugging purposes. One option was to override my Class’s ToString method and simply use Console.WriteLine(myObject). I do this on a few classes, and suddenly I have to maintain all these ToString methods whenever I change their properties or fields.

All that extra work, just for some debug statements? I think not – I’d rather the computer do the work for me. After all, it always knows what properties my objects have. So I wrote a method for automatically generating a “pretty” snapshot of an object’s state. C# code follows.

Console.WriteLine(AutoString(DBNull.Value));
// DBNull { }

Console.WriteLine(AutoString("A String", true));
// String
// {
//   FirstChar:      A
//   Length:         8
//   m_firstChar:    A
//   m_stringLength: 8
// }

Console.WriteLine(AutoString(new Customer
{
    Id = 12,
    Name = "Smith",
    Address = new Address
    {
        City = "Springfield"
    }
}));
// Customer
// {
//   Address: TestApp.Address
//   Id:      12
//   Name:    Smith
//   Region:
// }

public static string AutoString(object obj, bool includeNonPublic = false)
{
    if (obj == null) return "null";

    Type type = obj.GetType();

    BindingFlags flags = BindingFlags.Instance | BindingFlags.Public;
    if (includeNonPublic)
        flags = flags | BindingFlags.NonPublic;

    List<MemberInfo> members = type.GetProperties(flags)
                                    .Where(property => property.GetIndexParameters().Length == 0)
                                    .Cast<MemberInfo>()
                                    .Concat(type.GetFields(flags))
                                    .OrderBy(member => member.Name)
                                    .ToList();

    StringBuilder sb = new StringBuilder();

    if (members.Count > 0)
    {
        sb.AppendLine(type.Name);
        sb.AppendLine("{");

        int longest = members.Max(m => m.Name.Length);
        foreach (MemberInfo member in members)
        {
            sb.Append("  ");
            sb.Append(member.Name);
            sb.Append(":");
            sb.Append(' ', longest - member.Name.Length + 1);
            sb.Append(GetValue(member as PropertyInfo, obj));
            sb.Append(GetValue(member as FieldInfo, obj));
            sb.AppendLine();
        }

        sb.Append("}");
    }
    else
    {
        sb.Append(type.Name);
        sb.Append(" { }");
    }

    return sb.ToString();
}

private static string GetValue(PropertyInfo property, object instance)
{
    if (property == null) return null;
    var value = property.GetValue(instance, null);
    if (value == null) return null;
    return value.ToString();
}

private static string GetValue(FieldInfo field, object instance)
{
    if (field == null) return null;
    var value = field.GetValue(instance);
    if (value == null) return null;
    return value.ToString();
}