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.
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
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.
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.
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");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With