在Visual Studio调试器中显示自定义顺序中的属性

时间:2015-02-13 17:06:17

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

在Visual Studio中,是否可以自定义在调试器中检查属性时的显示顺序?

这是一个类的例子,我真的很喜欢StartDate和EndDate彼此相邻,即使它们按字母顺序分开。

example

其他调试器选项可以通过DebuggerDisplayAttribute等属性进行自定义,因此我希望DisplayOrder能够存在另一个这样的属性。

[DebuggerDisplay("{Name}")]
public class Rule
{
    public string Name;
    public int MaxAge;
    public DateTime StartDate;
    public DateTime EndDate;
}

理想世界中,我希望能够按照我在类中定义的顺序在检查器中对属性进行排序(即使这需要设置调试器顺序属性)逐步增加每个属性)所以显示将如下所示:

ideal debugger

4 个答案:

答案 0 :(得分:4)

VS2019+ 中的

Pinnable Properties 是目前可行的方法,因为您可以使用数据提示内的 pin 按钮按正确顺序固定属性。

但是,在更通用、可重用的方法中,[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] 属性可用于有序属性名称和值对的数组。这使调试视图能够“展平”数组根,以正确的顺序列出属性。

进一步扩展 KyleMit's answer,并使用反射加载成员和字段列表,使这样的调试视图可重用:

[DebuggerDisplay("{Name}")]
[DebuggerTypeProxy(typeof(OrderedPropertiesView))]
public class Rule
{
    public string Name;
    public int MaxAge;
    public DateTime StartDate;
    public DateTime EndDate;        
}

public class OrderedPropertiesView
{
    [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
    public SimpleProperty[] Properties { get; }

    public OrderedPropertiesView(object input)
    {
        this.Properties = input.GetType()
            .GetFields(BindingFlags.Public | BindingFlags.Instance)
            .Select(prop => new SimpleProperty(prop, input))
            .ToArray();
    }

    [DebuggerDisplay("{Value}", Name = "{PropertyName,nq}")]
    public class SimpleProperty
    {
        public SimpleProperty(MemberInfo member, object input)
        {
            this.Value = GetValue(member, input);
            this.PropertyName = member.Name;
        }

        private object GetValue(MemberInfo member, object input)
        {
            switch (member)
            {
                case FieldInfo fi: return fi.GetValue(input);
                case PropertyInfo pi: return pi.GetValue(input);
                default: return null;
            }
        }

        public object Value { get; internal set; }
        public string PropertyName { get; internal set; }
    }
}

在调试器中看起来像这样:

datatip with ordered 'properties'

属性和字段的顺序可能无法通过反射来保证,但由于视图仅用于调试目的,所以应该足够了。如果不是,则可以手动构造 Properties 数组,限制了可重用性。在任何一种情况下,Properties 都不是真正的属性,因此扩展 SimpleProperty 数据提示如下所示:

expanded datatip showing PropertyName and Value properties of SimpleProperty

请注意,属性检查器 magnifyng glass 只能在扩展的 SimpleProperty.Value 中使用,这可能会带来不便。

答案 1 :(得分:2)

只需将JCL's suggestion上的球用完就可以使用#if DEBUG来计算属性。如果您想在调试器中获得一些额外信息,则只能在调试模式下添加字段,如下所示:

[DebuggerDisplay("{Name}")]
public class Rule
{
    public string Name;
    public int MaxAge;
    public DateTime StartDate;
    public DateTime EndDate;

#if DEBUG
    private string DateRange
    {
        get { return StartDate.ToString("dd/MM/yyyy") + " - "+
                     EndDate.ToString("dd/MM/yyyy");
        } 
    }
#endif

}

看起来像这样:

debugger

这会将信息一起呈现,但仍会向检查员添加噪音。

答案 2 :(得分:1)

您可以右键单击变量和“添加监视”并将其按顺序放置。

enter image description here

答案 3 :(得分:1)

只是为了在JCL's suggestion上运行球以使用DebuggerTypeProxyAttribute,您可以添加内部类或公共类作为调试视图的容器

您可以使用数字强制在调试器视图类上对属性进行排序,而无需更改API或运行时代码的性能。

以下是DebuggerTypeProxy的类:

[DebuggerDisplay("{Name}")]
[DebuggerTypeProxy(typeof (RuleDebugView))]
public class Rule
{
    public string Name;
    public int MaxAge;
    public DateTime StartDate;
    public DateTime EndDate;

    internal class RuleDebugView
    {
        public string _1_Name;
        public int _2_MaxAge;
        public DateTime _3_StartDate;
        public DateTime _4_EndDate;

        public RuleDebugView(Rule rule)
        {
            this._1_Name = rule.Name;
            this._2_MaxAge = rule.MaxAge;
            this._3_StartDate = rule.StartDate;
            this._4_EndDate = rule.EndDate;
        }
    }
}

在调试器中看起来像这样:

debugger

它不是世界上最干净的东西,但确实做了一点。