【问题标题】:Possible to accessing child "DebuggerDisplay" attribute of property?可以访问属性的子“DebuggerDisplay”属性吗?
【发布时间】:2013-06-22 06:09:07
【问题描述】:

当前状态

有两个类:

[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 类的知识。

我希望有更多方法可以将B 类型的DebuggerDisplay 的值“注入”到A 类中该类型的实例。

问题

是否可以通过某种方式访问​​“has-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();
        }
    }
}

【问题讨论】:

标签: c# .net visual-studio debugging debuggerdisplay


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    [免责声明我隶属于 OzCode]

    您可以使用支持嵌套调试信息的 OzCode 的 Reveal feature
    好处是您不需要更改生产代码,一旦为实例定义了它,它将自动用于该类型的所有实例。

    【讨论】:

      【解决方案3】:

      拼凑一些我想出的解决方案。它有一个警告它希望你遵循https://blogs.msdn.microsoft.com/jaredpar/2011/03/18/debuggerdisplay-attribute-best-practices/

      [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 所需的通用约束和接口)。

      【讨论】:

        猜你喜欢
        • 2018-07-02
        • 1970-01-01
        • 2012-01-03
        • 2011-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多