[英]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
類具有B
類A
知識。
我想有更多的方法將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();
}
}
}
把我想出的這個解決方案的一些事情拼湊在一起。 它有一個警告,它希望您遵循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.