Существует ли метод для визуализации объекта с использованием DebuggerDisplayAttribute
У меня есть несколько классов, которые украшены DebuggerDisplayAttribute.
Я хочу иметь возможность добавлять операторы трассировки в модульные тесты, которые будут отображать экземпляры этих классов.
Существует ли в.NET Framework метод, который будет отображать объект, отформатированный с использованием DebuggerDisplayAttribute (или использовать метод.ToString(), если не определен DebuggerDisplayAttribute)?
РЕДАКТИРОВАТЬ
Чтобы уточнить, я надеялся, что в Framework может быть что-то встроено. Я знаю, что могу получить свойство Value из DebuggerDisplayAttribute, но затем мне нужно отформатировать мой экземпляр, используя строку формата, представленную 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 ответа
Это может быть неплохо - но строка формата DebuggerDisplayAttribute оценивается отладчиком так же, как он вычисляет выражения, которые вы вводите в окнах Watch или Immediate. Вот почему вы можете поместить произвольные выражения в фигурные скобки, как {FirstName + " " + LastName}
,
Поэтому, чтобы оценить их в своем коде, вам необходимо встроить отладчик Visual Studio в ваше приложение. Вероятно, не произойдет. (Гринь)
Лучше всего, вероятно, взять всю логику форматирования, которая в настоящее время находится в строке формата DebuggerDisplay, и вместо этого сделать ее методом. Тогда вы можете вызывать этот метод из своего кода. Ваш атрибут DebuggerDisplay в итоге ничего не делает, кроме вызова метода.
[DebuggerDisplay("{Inspect()}")]
public class MyClass {
public string Inspect() { ... }
}
Этот метод не реализует точно то, что 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();
}
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()