是否存在使用DebuggerDisplayAttribute渲染对象的方法?

7
我有一些被DebuggerDisplayAttribute修饰的类。
我想能够在单元测试中添加跟踪语句,以显示这些类的实例。
.NET Framework中是否存在一种方法,可以显示使用DebuggerDisplayAttribute格式化的对象(如果未定义DebuggerDisplayAttribute,则返回使用.ToString())?
编辑:
为了澄清,我希望Framework中可能会有内置的东西。我知道我可以从DebuggerDisplayAttribute获取Value属性,但我需要使用由DebuggerDisplayAttribute.Value表示的格式字符串来格式化我的实例。
如果我自己编写,我预计将创建以下类型的扩展方法:
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);
}
3个回答

4

这种方法不会像DebuggerDisplayAttribute在调试器中提供的那样完美实现,但这是我在我的代码中一直在使用的。它可以覆盖我们代码库中约90%(或更多)的情况。如果你能将其完善以覆盖更多的情况,我很乐意看到你的改进!

    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

这可能很好,但DebuggerDisplayAttribute的格式字符串由调试器评估,就像它评估您在“监视”窗口或“立即”窗口中键入的表达式一样。这就是为什么您可以在括号内放置任意表达式,例如{FirstName + " " + LastName}

因此,要在代码中评估这些表达式,您需要将Visual Studio调试器嵌入到应用程序中。这可能不太可能发生。(笑)

您最好的选择可能是将当前在DebuggerDisplay格式字符串中的所有格式逻辑制作成一个方法。然后您可以自由地从代码中调用该方法。您的DebuggerDisplay属性最终什么都不会做,只会调用该方法。

[DebuggerDisplay("{Inspect()}")]
public class MyClass {
    public string Inspect() { ... }
}

谢谢。按照您所描述的方式编写自己的方法有点违背我尝试实现的目的。我已经选择重写相关类的ToString()方法。 - Joe
如果您的应用程序代码没有为ToString()分配任何含义,那么是的,这更简单。在某些情况下,ToString()已经有了意义(例如在列表框中显示对象),在这些情况下,DebuggerDisplay加上一个方法仍然很有用。 - Joe White
你不需要“将Visual Studio调试器嵌入到你的应用程序中”来编写一个能提供价值的方法。我猜大多数使用DebuggerDisplay的情况都是简单的属性值,实现这些将会是一个有价值的方法。 - Kenneth LeFebvre

1

DebuggerDisplayAttribute有一个Value属性,可以返回您想要的内容。

因此,您可能会使用类似于以下内容的东西:

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

你甚至可以将它放入扩展方法中:

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

你可以在每个对象上调用它:myObject.ToDebugString()


2
是的,我知道我可以自己编写,问题是是否已经存在任何东西。您的示例没有帮助-它只会显示属性的格式字符串,而不是使用格式字符串格式化obj。 - Joe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接