Подтвердить что ты не робот

Цепочный отладчикDisplay для сложных типов

У меня есть несколько классов, определяющих атрибут DebuggerDisplay. Я хочу знать, есть ли способ определить один атрибут DebuggerDisplay на основе другого. Если у меня есть следующие классы:

[DebuggerDisplay ("Text = {Text}")]
class A
{
    public string Text {get;set;}
}

[DebuggerDisplay ("Property = {Property}")]
class B
{
    public A Property {get; set;}
}

Я хотел бы видеть в экземплярах класса B, как это определено в атрибуте класса DebuggerDisplay класса. Вместо этого я получаю метод класса ToString() на отладчик при просмотре объектов класса B.

4b9b3361

Ответ 1

Не уверен, правильно ли я понял вашу проблему, но попробуйте:

[DebuggerDisplay("Property = {Property.Text}")]
public class B
{
    public A Property { get; set; }
}

Отобразится свойство A Text.

Если вам нужно более сложное управление, вы можете использовать DebuggerTypeProxyAttribute

Ответ 2

Я знаю, что это не "правильное кодирование", но поскольку я не могу связать свои права, я решил вернуться к старым путям. Просто переопределите метод ToString(). то цепочка - это кусок пирога.

    public partial class Tld
{
    public override string ToString()
    {
        return this.Name;
    }    
}

public partial class Domain
{
    public override string ToString()
    {
        return this.DomainName + "." +this.Tld.ToString();
    } 

    public  Domain (string domain, string tld):this( domain, new Tld(tld))
    {

    }
    public Domain(string domain, Tld tld):this()
    {
        this.DomainName = domain;
        this.Tld = tld;

    }
}


public partial class Url
{
    public override string ToString()
    {
        return this.Scheme + "://" + this.Subdomain + this.Domain.ToString() + ((string.IsNullOrWhiteSpace(this.Path)) ? "" :  this.Path);
    }
    public Url (string scheme, string subdomain, string domain, string tld, string path):this(new Tld(tld),domain, subdomain,scheme,path){}

    public Url(Tld tld, string domainName, string subdomain, string scheme, string path): this(new Domain(domainName, tld),subdomain,scheme,path){}

     public Url(Domain domain, string subdomain, string scheme, string path):this()
    {
        this.Domain = domain;
        this.Path = path;
        this.Scheme = scheme;
        this.Subdomain = subdomain;

    }

}


public void Domain_Create_GOOD()
    {
     Domain expected = new Domain("google","co.nz");

    }

Ответ 3

От https://blogs.msdn.microsoft.com/jaredpar/2011/03/18/debuggerdisplay-attribute-best-practices/ (я добавил директивы условной компиляции)

#if DEBUG
    [DebuggerDisplay("{DebuggerDisplay}")]
    public sealed class Student {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    private string DebuggerDisplay {
        get { return string.Format("Student: {0} {1}", FirstName, LastName);}
    }
}
#endif

Это похоже на ответ Микки Перлштейна (ясное свойство, которое форматирует строку отладчика), без необходимости переопределять ToString() (который может понадобиться для другой цели.)

источник также содержит ряд других полезных советов для DebuggerDisplay, включая некоторые соображения производительности.

Изменить


Так как это отладочный код, так или иначе, это не так плохо, чтобы нарушать ООП (доступ к частной собственности извне)... но мы довольно сильно нарушаем его.

private string DebuggerString {
    get {
        StringBuilder sb = new StringBuilder();
        sb.Append("Whatever you want your Parent class' Debugger Text To Say");

        var properties = typeof(GroupQuote).GetProperties()
            //get the properties with the DebuggerDisplay attribute and our property
            .Where(x =  > x.PropertyType.IsDefined(typeof(DebuggerDisplayAttribute))
                     && x.PropertyType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).Any(y =  > y.Name == "DebuggerString"));

        foreach(PropertyInfo property in properties) {
            object itemWithProperty = property.GetValue(this);
        //we have to check our property for null, otherwise trying to get its DebuggerString property will throw an exception
        if (itemWithProperty != null) {
                PropertyInfo privateDebuggerProperty = property.PropertyType.GetProperty("DebuggerString", BindingFlags.NonPublic | BindingFlags.Instance);
                sb.Append(privateDebuggerProperty.GetValue(itemWithProperty)as string);
            }
        }
        return sb.ToString();
    }
}

Пример

В коде, который я написал и протестировал это, у меня были некоторые свойства моего родительского класса, показывающие, что DebuggerDisplay был определен, когда он не был (возможно, вещь наследования?). Я добавил дополнительную проверку, чтобы мы только искали DebuggerString по свойствам, которые на самом деле есть.