by Oliver
16. September 2011 20:06
Lately, I was having trouble debugging certain parts of my code in Visual Studio, and all I wanted to know was the value of some variable at some point in time. Well, I’d use some logging if I could just get at that value easily. But for some objects I don’t really know what I’m looking for or where I should be looking for it. So just give me the values of all the members of that object, will ya? And could you recurse that? But no deeper than 3 levels, alright? Or let’s say… 5?
public static string ToDebugString(this object obj, int maxdepth, int depth=0)
{
if (obj == null)
return "null";
if (obj is IConvertible)
return obj.ToString();
if (depth >= maxdepth)
return "...";
var sb = new StringBuilder();
if (depth > 0)
sb.AppendLine();
foreach (var propertyInfo in obj.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance))
{
sb.Append(new string(' ', 2*depth)).Append(propertyInfo.Name).Append(": ");
try
{
var value = propertyInfo.GetValue(obj, new object[0]);
sb.AppendLine(ToDebugString(value, maxdepth, depth + 1));
}
catch (Exception ex)
{
sb.AppendLine(string.Format("[{0}]", ex.Message));
}
}
// remove newline from end of string
var newLine = Environment.NewLine;
if (sb.Length >= newLine.Length)
sb.Replace(newLine, "", sb.Length - newLine.Length, newLine.Length);
return sb.ToString();
}
With this little helper I can now simply call anyobject.ToDebugString(4 /* maxdepth */) and I get a nicely formatted debug view of that object; e.g. Request.Url.ToDebugString(3) gives me:
AbsolutePath: /logg.aspx
AbsoluteUri: http://localhost:55235/logg.aspx
Authority: localhost:55235
Host: localhost
HostNameType: Dns
IsDefaultPort: False
IsFile: False
IsLoopback: True
IsUnc: False
LocalPath: /logg.aspx
PathAndQuery: /logg.aspx
Port: 55235
Query:
Fragment:
Scheme: http
OriginalString: http://localhost:55235/logg.aspx
DnsSafeHost: localhost
IsAbsoluteUri: True
Segments:
Length: 2
LongLength: 2
Rank: 1
SyncRoot:
Length: 2
LongLength: 2
Rank: 1
SyncRoot: ...
IsReadOnly: False
IsFixedSize: True
IsSynchronized: False
IsReadOnly: False
IsFixedSize: True
IsSynchronized: False
UserEscaped: False
UserInfo:
Nice
Right now this method chokes on indexed properties but once I’ll need it I’ll go and look for a way to include them. It also chokes any exceptions on the way to just get the job done.
Happy coding!