可以访问属性的子“DebuggerDisplay”属性吗?

当前状态

有两个class:

[DebuggerDisplay(@"One = {One}, two = {Two}")] public class A { public int One { get; set; } public B Two { get; set; } } [DebuggerDisplay(@"Three = {Three}")] public class B { public int Three { get; set; } } 

使用它们:

 var a = new A {One = 5, Two = new B {Three = 10}}; 

在调试器内部,显示在a处的工具提示值

一个= 5,两个= {DebuggerDisplayTest.B}

目标

我想要的是类似的东西

一个= 5,两个=’三= 10′

我知道这可以通过重写B类的ToString()方法来实现。 这只是感觉不对,因为我在我的应用程序中编写代码仅用于调试。

我也知道使用类似的字符串

 [DebuggerDisplay(@"One = {One}, two = 'Three = {Two.Three}'")] 

也会工作。 这对我来说也不合适,因为它要求A级知道B级。

我想有更多的方法将类型BDebuggerDisplay的值“注入”到类A中该类型的实例。

是否可以以某种方式访问​​“has-a”合成类的DebuggerDisplay属性中的成员的DebuggerDisplay属性?

更新

可能,根据这个SO答案 ,我的要求是不可能的。 也许一个好的解决方案是覆盖B类中的ToString并执行一些if..else并使用Debugger.IsAttached属性仅在调试器内部表现不同。

就像是:

 [DebuggerDisplay(@"Three = {Three}")] public class B { public int Three { get; set; } public override string ToString() { if (Debugger.IsAttached) { return string.Format(@"Three = {0}", Three); } else { return base.ToString(); } } } 

从OP复制可能的解决方案

可能,根据这个SO答案 ,我的要求是不可能的。 也许一个好的解决方案是覆盖B类中的ToString并执行一些if..else并使用Debugger.IsAttached属性仅在调试器内部表现不同。

就像是:

 [DebuggerDisplay(@"Three = {Three}")] public class B { public int Three { get; set; } public override string ToString() { if (Debugger.IsAttached) { return string.Format(@"Three = {0}", Three); } else { return base.ToString(); } } } 

[免责声明我隶属于OzCode]

您可以使用OzCode的Revealfunction ,该function支持嵌套的调试信息。 揭示行动!
优点是您不需要更改生产代码,一旦为实例定义它,它将自动用于该类型的所有实例。

拼凑了一些我已经提出这个解决方案的东西。 它有一个警告,它希望你遵循https://blogs.msdn.microsoft.com/jaredpar/2011/03/18/debuggerdisplay-attribute-best-practices/ 。 使用C#6( 与Visual Studio 2013兼容 )

 [DebuggerDisplay("{DebuggerDisplay,nq}")] public class B { public int Three { get; set; } private string DebuggerDisplay => $"Three = {Three}"; } [DebuggerDisplay("{DebuggerDisplay,nq}")] public class A { public int One { get; set; } public B Two { get; set; } private string DebuggerDisplay => $"One = {One}, two = {Two.ReadDebuggerDisplay()}"; } 

你需要确保你有适当的导入,你可以将这个帮助器放在与需要读取子调试器显示的代码相关的位置。

 public static class ReflectionHelper { // https://stackoverflow.com/a/13650728/37055 public static object ReadProperty( this object target, string propertyName) { var args = new[] {CSharpArgumentInfo.Create(0, null)}; var binder = Binder.GetMember(0, propertyName, target.GetType(), args); var site = CallSite>.Create(binder); return site.Target(site, target); } public static string ReadDebuggerDisplay( this object target, string propertyName = "DebuggerDisplay") { string debuggerDisplay = null; try { var value = ReadProperty(target, propertyName) ?? ""; debuggerDisplay = value as string ?? value.ToString(); } catch (Exception) { // ignored } return debuggerDisplay ?? $""; } } 

我认为这是一种非常公平的纯度和实用性平衡,可以降低实现这一目标的摩擦力。 如果您不太关心纯度,可以将DebuggerDisplay公开化。 我更喜欢ReadDebuggerDisplay以“无类型”方式运行(避免公共访问DebuggerDisplay所需的通用约束和接口)。