ADCollectionsVisualizer






4.63/5 (9投票s)
一个 VS2005 可视化工具,
Visual Studio 2005
Visual Studio 2008
左键单击 gadget 并拖动以移动它。左键单击 gadget 的右下角并拖动以调整其大小。右键单击 gadget 以访问其属性。

引言
ADCollectionsVisualizer 是一个 Visualizer 插件,适用于 Visual Studio 2005 和 Visual Studio 2008,可以方便地检查各种集合和字典类型的对象。
背景
Visual Studio 2005/2008 IDE 的一个出色的新功能是可以使用 Visualizers。这些是实用程序窗口,它们会附加到 Visual Studio 环境中的各种对象类型。当您将鼠标悬停在受支持对象类型的一个变量上时,弹出式工具提示中会出现一个放大镜图标,单击它将打开该特定变量的 Visualizer 窗口,从而更轻松地查看变量内容。
Visual Studio 默认包含几个 Visualizers,用于查看文本(纯文本、HTML 或 XML)以及更仔细地检查 DataTables。IDE 允许编写其他 Visualizers,例如 ADCollectionsVisualizer。
ADCollectionsVisualizer 允许以网格形式查看各种集合和字典类(以及继承自这些类的所有类的对象),并且如果需要,还可以将它们复制到剪贴板并保存到磁盘。
Using the Code
可以通过运行安装可执行文件来安装 visualizer,或者通过解压缩 DLL 并将其放置在相应的 My Documents\Visual Studio 2005\Visualizers 或 My Documents\Visual Studio 2008\Visualizers 目录中。
请注意,如果您从源代码编译 visualizer,可以使用构建事件自动将 visualizer 复制到安装目录。可以通过双击“我的项目”图标,然后选择“编译”选项卡并单击“构建事件”按钮来找到它( such a build event is configured within the provided project file — 您很可能需要将路径更改为您的 My Documents 目录所在的位置)。
完成此操作后,只需在调试模式下将鼠标悬停在 IDE 中的集合对象上。应出现一个小的放大镜图标;单击它以打开 visualizer。

Visualizer 支持多种集合类型的对象,包括:
System.Collections
类System.Collections.ArrayList
System.Collections.BitArray
System.Collections.HashTable
System.Collections.Queue
System.Collections.SortedList
System.Collections.Stack
System.Collections.Specialized
类System.Collections.Specialized.HybridDictionary
System.Collections.Specialized.ListDictionary
System.Collections.Specialized.NameValueCollection
System.Collections.Specialized.OrderedDictionary
System.Collections.Specialized.StringCollection
System.Collections.Specialized.StringDictionary
- 所有继承自
System.Collections.CollectionBase
的类 - 所有继承自
System.Collections.Specialized.NameObjectCollectionBase
的类
System.Collections.Generic
类System.Collections.Generic.Dictionary
System.Collections.Generic.List
System.Collections.Generic.LinkedList
System.Collections.Generic.Queue
System.Collections.Generic.SortedDictionary
System.Collections.Generic.SortedList
System.Collections.Generic.Stack
- IIS 类,由以下类使用:
System.Web.HttpRequest.Cookies
System.Web.HttpRequest.Files
System.Web.HttpRequest.Form
System.Web.HttpRequest.Headers
System.Web.HttpRequest.Params
System.Web.HttpRequest.QueryString
System.Web.HttpRequest.ServerVariables
System.Web.HttpResponse.Cookies
- VB6 兼容的集合
Microsoft.VisualBasic.Collection
(仅值 - 无法从此类集合中检索键)
代码本身包含三个主要类:
CollectionVisualizer
ObjectSource
PreviewForm
CollectionVisualizer
包含 visualizer 本身,以及所有 DebuggerVisualizer
程序集属性。这些属性有很多,用于处理 visualizer 支持的所有不同类型的集合和字典类。
<Assembly: DebuggerVisualizer(GetType(CollectionVisualizer),
GetType(ObjectSource), Target:=GetType(Collections.ArrayList),
Description:="Collection Visualizer")>
<Assembly: DebuggerVisualizer(GetType(CollectionVisualizer),
GetType(ObjectSource), Target:=GetType(Collections.BitArray),
Description:="Collection Visualizer")>
<Assembly: DebuggerVisualizer(GetType(CollectionVisualizer),
GetType(ObjectSource), Target:=GetType(Collections.Hashtable),
Description:="Collection Visualizer")>
[...etc...]
请注意,项目中的两个类在每个属性中都有引用:第一个是负责执行工作的 CollectionVisualizer
类,第二个是 ObjectSource
,它将所有数据打包成可序列化的形式,以便 visualizer 访问。有关详细信息,请参见下文。每个属性中的第三个类引用指向 visualizer 要使用的类类型。这会针对每个属性而变化,重复的属性允许所有支持的类由同一个 visualizer 类处理。
如果您想了解更多关于如何编写 Visualizers 的信息,您可以在 The Code Project 中找到其他详细解释这些内容的文章。
最新版本现在还支持 Generic collection 对象。这些对象在程序集属性中以稍不同的方式指定。
<Assembly: DebuggerVisualizer(GetType(CollectionVisualizer),
GetType(ObjectSource),
Target:=GetType(collections.Generic.Dictionary(Of ,)),
Description:="Collection Visualizer")>
<Assembly: DebuggerVisualizer(GetType(CollectionVisualizer),
GetType(ObjectSource), Target:=GetType(collections.Generic.List(Of )),
Description:="Collection Visualizer")>
[...etc...]
泛型类类型使用类名后跟括号中的 Of
关键字来指定,但没有指定类类型。当需要多个类类型时,使用逗号分隔这些类型,但同样不指定类型。这使得 visualizer 能够处理泛型类,而不管它们存储的数据类型是什么。
Visualizer 使用自定义的 VisualizerObjectSource
来打包要可视化的数据。IDE 会序列化要可视化的数据,而 ADCollectionsVisualizer 支持的一些集合类型无法序列化。为了解决这个问题,ObjectSource
类会从集合中提取所有数据,并将其放入 ADO.NET DataTable
中,将每个对象的value表示为简单的 String
。然后将此 DataTable
序列化并传递给 visualizer。ObjectSource
类负责识别所有受支持的不同集合类型并将其数据解码到 DataTable
中。对大多数类型来说这很简单,但有些类型(特别是继承自 NameObjectCollectionBase
的对象)比它们看起来要棘手一些。
最后,PreviewForm
在屏幕上显示要可视化的数据。它使用 DataGrid
进行展示,并提供将集合数据复制到剪贴板或以 CSV、文本或 XML 格式保存到磁盘的功能。
关注点
有几个代码区域可能会对以前未接触过它们的人有用或有趣——它们确实让我困惑了一段时间。
第一个是访问派生自 NameObjectCollectionBase
的对象内值 Thus 代码。我可以看到该类中有两个受保护的成员,名为 BaseGetAllKeys
和 BaseGetAllValues
— 显然,这些正是我需要从集合中提取所有数据的。但是,由于它们是受保护的,我的代码无法直接访问它们。
我使用了一种相当hacky(hacky:不规范但有效的)反射技术来访问这些函数。我绝对不建议在生产代码中使用此类技术,但在 visualizer 所做事情的上下文中,我认为它们是一种可接受的技术。没有它们,我将无法支持基于此类类的集合。
第二个需要一些试验和研究才能正确处理的是 DataGrid
的自定义。默认情况下,网格允许编辑值(这是 visualizer 目前不支持的),并用灰色背景突出显示选定的单元格。我创建了一个名为 CustomGridTextBoxColumn
的类,它继承自 .NET 的 DataGridTextBoxColumn
,并添加了一些代码来防止编辑并正确控制单元格的前景色和背景色。尽管设置起来有点麻烦,但它效果非常好,并且提供了我想要的确切功能。
实现 DataGridTextBoxColumn
的代码如下:
'''
''' A custom DataGridTextBoxColumn that provides some changed functionality,
''' required by the visualizer
'''
Public Class CustomGridTextBoxColumn
Inherits DataGridTextBoxColumn
'''
''' When the grid attempts to go into Edit mode, this method will return
''' without calling into the base class, and so prevents the edit from
''' starting.
'''
Protected Overrides Sub Edit(ByVal source As CurrencyManager,
ByVal rowNum As Integer, ByVal bounds As System.Drawing.Rectangle,
ByVal [readOnly] As Boolean, ByVal displayText As String,
ByVal cellIsVisible As Boolean)
Return
End Sub
'''
''' The grid normally paints the active cell with a different colour to
''' the other cells. As our grid is read-only, this isn't a desirable
''' effect. This overridden Paint method
''' ensures that the cell is always painted to look the same, regardless
''' of whether it is active or not. We will also render Null values in
''' grey to distinguish them from the string "(null)".
'''
Protected Overrides Sub Paint(ByVal g As System.Drawing.Graphics,
ByVal bounds As System.Drawing.Rectangle,
ByVal source As System.Windows.Forms.CurrencyManager,
ByVal rowNum As Integer, ByVal backBrush As System.Drawing.Brush,
ByVal foreBrush As System.Drawing.Brush,
ByVal alignToRight As Boolean)
Try
'Create a brush for the background
backBrush = New SolidBrush(SystemColors.Window)
'Retrieve the value for this cell
Dim o As Object = Me.GetColumnValueAtRow(source, rowNum)
'Is this a Null value?
If o Is DBNull.Value Then
'Yes, so we'll use grey text
foreBrush = New SolidBrush(SystemColors.GrayText)
Else
'This is a normal value, we'll use the standard foreground
'text colour
foreBrush = New SolidBrush(SystemColors.ControlText)
End If
'Call into the base class to do the work
MyBase.Paint(g, bounds, source, rowNum, backBrush, foreBrush,
alignToRight)
Finally
'Clean up
If backBrush IsNot Nothing Then backBrush.Dispose()
If foreBrush IsNot Nothing Then foreBrush.Dispose()
End Try
End Sub
End Class
如您所见,重写了两个类过程。Edit
过程会立即退出,而不调用基类。这会阻止编辑的发生。Paint
过程确实会调用基类(并且仍然是文本实际绘制发生的地方),但在执行之前,它会替换将要使用的前景和背景画笔,并用自己的画笔替换它们,以确保它完全控制颜色。
如果您想了解更多关于更改和扩展 DataGrid
行为的信息,您可以在 George Shepherd 的 Windows Forms FAQ 的 DataGrid 部分找到大量信息。
历史
版本 1.2 (2008-09-10)
- 添加了对
System.Collections.Generic
类的支持 - 添加了 Visual Studio 2008 支持
版本 1.1 (2007-09-14)
- 添加了对继承自
Collections.CollectionBase
的集合的支持 - 发布了源代码
版本 1.0 (2007-06-03)
- 首次发布