-1

I'm trying to implement the common/general DebuggerDisplay attribute to avoid formatting it for every single usage which would simply show every property of the class. That's what I've achieved so far, my extension method looks like this

public static class DebuggerExtension
{
    public static string ToDebuggerString(this object @this)
    {
        var builder = new StringBuilder();
        foreach (var property in @this.GetType().GetProperties())
        {
            if (property != null)
            {
                var value = property.GetValue(@this, null)?.ToString();
                builder.Append($"{property.Name}: {value}, ");
            }
        }

        return builder.ToString();
    }
}

and I'm calling it like this and it basically works:

[DebuggerDisplay($"{{this.ToDebuggerString()}}")]

My questions are:

  1. Is there any existing extension to generate the DebuggerDisplay string? The built in VS implementation just adds the method which returns ToString() which doesn't really help
  2. Can I call the method on some compiler-checked way, not as a string? "this." is obviously not available in the attribute arguments. Maybe any expression?
  3. Any other possible solutions?
VladL
  • 12,769
  • 10
  • 63
  • 83

1 Answers1

0

Have you tried using 'ToDebuggerString()' again instead of 'ToString()' in extension method?
It may interest you. Visual Studio's Natvis Debugging Framework Tutorial

The example below may be helpful to you. (It may be missing!)

public static class DebuggerExtension
{
    public static string ToDebuggerDisplay(this object o)
    {
        if (object.ReferenceEquals(o, null))
            return "null";
        else if (o is string)
            return string.Format("\"{0}\"", (string)o);
        else if ((o is DateTime) || (o is TimeSpan))
            return string.Format("{{{0}}}", o);
        else if (o is System.Collections.ICollection)
            return string.Format("{{Count={0}}}", ((System.Collections.ICollection)o).Count);
        else if (o is System.Collections.IEnumerable)
        {
            int nCount = 0;
            System.Collections.IEnumerator e = ((System.Collections.IEnumerable)o).GetEnumerator();
            while (e.MoveNext())
            {
                nCount++;
            }
            return string.Format("{{Count={0}}}", nCount);
        }

        Type objType = o.GetType();

        if (objType.IsPrimitive || objType.IsEnum)
            return o.ToString();
        else if (objType.IsArray)
            return string.Format("{{Count={0}}}", ((Array)o).Length);

        PropertyInfo[] propertyInfos = objType.GetProperties(BindingFlags.Instance
            | BindingFlags.Public
            | BindingFlags.GetProperty
            | BindingFlags.DeclaredOnly);

        string retVal = "{";
        int ndx = 0;
        foreach (PropertyInfo pi in propertyInfos)
        {
            if (!pi.CanRead)
                continue;

            DebuggerBrowsableAttribute attr = pi.GetCustomAttribute<DebuggerBrowsableAttribute>();
            if (!object.ReferenceEquals(attr, null) && (attr.State == DebuggerBrowsableState.Never))
                continue;

            if (ndx++ > 0)
                retVal += " ";

            retVal += string.Format("{0}={1}", pi.Name, pi.GetValue(o).ToDebuggerDisplay());

            if (ndx > 2)
            {
                retVal += " ...";
                break;
            }
        }
        retVal += "}";

        return (ndx > 0) ? retVal : o.ToString();
    }
}

Uses

[DebuggerDisplay(@"{this.ToDebuggerDisplay(),nq}")]
gerdogdu
  • 44
  • 5