Chaining DebuggerDisplay on complex types

大憨熊 提交于 2019-12-18 07:35:01

问题


I have several classes defining the DebuggerDisplay attribute. I want to know if there is a way to define one DebuggerDisplay attribute based on another one. If I have the following classes:

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

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

I would like to see on instances of B the A class as it is defined on the class A DebuggerDisplay attribute. Instead of that I'm getting the class A ToString() method onto the debugger while viewing class B objects.


回答1:


Not sure if I understood your problem correctly but try:

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

This will Display the A's Text property.

If you need more complex control you can use DebuggerTypeProxyAttribute




回答2:


I know this isn't "correct coding" but since I can't chain my entites, I have decided to get back to the old ways. Just override the ToString() method. then chaining is a piece of cake.

    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:


From https://blogs.msdn.microsoft.com/jaredpar/2011/03/18/debuggerdisplay-attribute-best-practices/ (I added the conditional compilation directives)

#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

This is similar to Mickey Perlstein's answer (clear Property that formats the debugger's string) without needing to override ToString() (which might be needed for another purpose after all.)

The source also has a number of other good tips for DebuggerDisplay, including some performance considerations.

Edit


Since this is debugging code anyways it's not as bad to violate OOP (accessing private property from outside)...but we're violating it pretty hard here.

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();
    }
}

In the code I wrote and tested this in I was having some properties of my Parent class showing that DebuggerDisplay was defined when it wasn't (possibly an inheritance thing?). I added an additional check so that we only look for DebuggerString on properties that actually have it.



来源:https://stackoverflow.com/questions/8677795/chaining-debuggerdisplay-on-complex-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!