7

I have a number of classes that are decorated with DebuggerDisplayAttribute.

I want to be able to add trace statements to Unit Tests that will display instances of these classes.

Does there exist a method in the .NET Framework that will display an object formatted using DebuggerDisplayAttribute (or fall back to using .ToString() if no DebuggerDisplayAttribute is defined)?

EDIT

To clarify, I was hoping there might be something built into the Framework. I know I can get the Value property from DebuggerDisplayAttribute, but I then need to format my instance using the format string represented by DebuggerDisplayAttribute.Value.

If I roll my own, I'd envisage an extension method along the following lines:

public string FormatDebugDisplay(this object value)
{
    DebugDisplayAttribute attribute = ... get the attribute for value ...
    if (attribute = null) return value.ToString();

    string formatString = attribute.Value;

    ??? How do I format value using formatString ???
    return SomeFormatMethod(formatString, value);
}
Joe
  • 122,218
  • 32
  • 205
  • 338

3 Answers3

4

This method will not implement exactly what DebuggerDisplayAttribute provides in the debugger, but this is what I have been using in my code. It covers about 90% (or more) of the cases we experience in our codebase. If you fix it up to cover even more cases, I'd love to see your enhancements!

    public static string ToDebuggerString(this object @this)
    {
        var display = @this.GetType().GetCustomAttributes(typeof (DebuggerDisplayAttribute),false).FirstOrDefault() as DebuggerDisplayAttribute;
        if (display == null)
            return @this.ToString();

        var format = display.Value;
        var builder = new StringBuilder();
        for (var index = 0; index < format.Length; index++)
        {
            if (format[index] == '{')
            {
                var close = format.IndexOf('}', index);
                if (close > index)
                {
                    index++;
                    var name = format.Substring(index, close - index);
                    var property = @this.GetType().GetProperty(name);
                    if (property != null)
                    {
                        var value = property.GetValue(@this, null).ToString();
                        builder.Append(value);
                        index += name.Length;
                    }
                }
            }
            else
                builder.Append(format[index]);
        }
        return builder.ToString();
    }
3

That might be nice -- but DebuggerDisplayAttribute's format string is evaluated by the debugger, the same way it evaluates expressions you type into the Watch windows or the Immediate window. That's why you can put arbitrary expressions inside the braces, like {FirstName + " " + LastName}.

Therefore, to evaluate these in your code, you would need to embed the Visual Studio debugger into your app. Probably not gonna happen. (grin)

Your best bet is probably to take all the formatting logic that's currently in your DebuggerDisplay format string, and make it a method instead. Then you're free to call that method from your code. Your DebuggerDisplay attribute ends up doing nothing but calling the method.

[DebuggerDisplay("{Inspect()}")]
public class MyClass {
    public string Inspect() { ... }
}
Joe White
  • 94,807
  • 60
  • 220
  • 330
  • Thanks. Writing my own method in the way you describe kind of defeats the purpose of what I was trying to achieve. I've gone with overriding ToString() for the classes in question. – Joe Aug 25 '10 at 05:35
  • If your application code doesn't assign any meaning to ToString(), then yes, that's simpler. In some cases, ToString() already has a meaning (e.g. to display the object in a listbox), and in those cases, DebuggerDisplay plus a method can still be useful. – Joe White Aug 25 '10 at 17:01
  • You wouldn't need to "embed the Visual Studio debugger into your app" to write a method that would provide value. I would suspect that _most_ uses of DebuggerDisplay are simple property values, and implementing that much would be a valuable method. – Kenneth LeFebvre Oct 30 '15 at 20:53
1

The DebuggerDisplayAttribute has a Value property which returns what you want.

So you could probably use something like this:

var attribute = obj.GetType().
    GetCustomAttributes(typeof(DebuggerDisplayAttribute), false);
return (attribute == null) ? obj.ToString() : attribute.Value;

You could even put this into an extension method:

public static string ToDebugString(this object obj)
{
    var attribute = obj.GetType().
        GetCustomAttributes(typeof(DebuggerDisplayAttribute), false);
    return (attribute == null) ? obj.ToString() : attribute.Value;
}

the you can call it on every object: myObject.ToDebugString()

M4N
  • 94,805
  • 45
  • 217
  • 260
  • 2
    Yes, I know I can roll my own, the question was whether anything already exists. Your sample doesn't help - it will just display the format string of the attribute rather than formatting obj using the format string. – Joe May 08 '10 at 13:46