簡體   English   中英

可以訪問屬性的子“DebuggerDisplay”屬性嗎?

[英]Possible to accessing child “DebuggerDisplay” attribute of property?

當前狀態

有兩個類:

[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類具有BA知識。

我想有更多的方法將B類型的DebuggerDisplay的值“注入”到A類中該類型的實例。

問題

是它在某種程度上可以訪問DebuggerDisplay內部成員的屬性DebuggerDisplay一個“有,一個”合成后類的屬性?

更新

可能,根據這個 SO answer ,我的要求是不可能的。 也許一個好的解決方案是覆蓋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 answer ,我的要求可能是不可能的。 也許一個好的解決方案是覆蓋 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 的Reveal 功能,該功能支持嵌套調試信息。 在行動中揭曉!
好的一面是您不需要更改您的生產代碼,一旦您為實例定義它,它將自動用於該類型的所有實例。

把我想出的這個解決方案的一些事情拼湊在一起。 它有一個警告,它希望您遵循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 所需的通用約束和接口)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM