2013-06-25 67 views
9

現狀可能訪問屬性的子「DebuggerDisplay」屬性?

有兩類:

[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顯示工具提示值

One = 5,two = {D ebuggerDisplayTest.B}

目標

我想是一樣的東西

一個= 5,二= '三= 10'

我知道這可以通過重寫類BToString()方法來實現。這只是感覺不對,因爲我只是在應用程序中編寫代碼來進行調試。

我也知道,使用類似於

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

會工作的字符串了。這也不適合我,因爲它要求類A具有類B的知識。

我想有更多的方法將類型BDebuggerDisplay的值「注入」類A中的那個類型的實例。

問題

是它在某種程度上可以訪問「有,一個」合成後級的DebuggerDisplay屬性中成員的DebuggerDisplay屬性?

更新

也許,我的要求是不可能的,因爲每this SO answer。也許一個好的解決方案是覆蓋類B中的ToString,並且執行一些if..else並且使用Debugger.IsAttached property僅在調試器內表現不同。

喜歡的東西:

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

相關:http://stackoverflow.com/questions/8677795/chaining-debuggerdisplay-on-complex-types –

回答

3

複製從OP

可能的解決方案或許,我的要求是不可能的,因爲每本SO answer。也許一個好的解決方案是重寫類B中的ToString,並執行一些if..else,並使用Debugger.IsAttached property在調試器內表現不同。

喜歡的東西:

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

[免責聲明我隸屬於OzCode]

您可以使用OzCode的Reveal feature支持嵌套的調試信息。 Reveal in action!
好的一面是,你不需要改變你的生產代碼,一旦你爲一個實例定義它,它將自動用於該類型的所有實例。

1

把這個解決方案提出來幾件事。它有這樣的警告,它期望你遵循https://blogs.msdn.microsoft.com/jaredpar/2011/03/18/debuggerdisplay-attribute-best-practices/。使用C#6(compatible with 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<Func<CallSite, object, object>>.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) ?? "<null object>"; 

      debuggerDisplay = value as string ?? value.ToString(); 
     } 
     catch (Exception) 
     { 
      // ignored 
     } 
     return debuggerDisplay ?? 
       $"<ReadDebuggerDisplay failed on {target.GetType()}[{propertyName}]>"; 
    } 
} 

我覺得這是一個非常公平的純淨和實用主義的平衡,以降低實現這一目標的摩擦。如果你不太關心純度,你可以公開DebuggerDisplay。我更喜歡ReadDebuggerDisplay以「無類型」方式操作(避免了公共訪問DebuggerDisplay所需的通用約束和接口)。