Visual Studio Visualizer:第一部分





5.00/5 (8投票s)
本项目展示了一个变通方法,可以使不可序列化的对象可用于自定义可视化工具。
引言
项目网站:http://vsdatawatchers.codeplex.com
添加 Visual Studio 可视化工具以查看数据
- 数据集;
- 数据表;
- 数据行;
- 数据视图;
- 数据行视图;
- 数据行集合。
第二部分可在以下地址找到: https://codeproject.org.cn/Articles/584739/Visual-Studio-Visualizer-Part-2-Entity-Framework
第三部分可在以下地址找到:https://codeproject.org.cn/Articles/599504/Visual-Studio-Visualizer-Part-3-Collection-visuali
使用代码
访问项目主页,下载您需要的版本(2010 或 2012),解压缩,并将 DLL 放在正确的文件夹中,即 Documents\Visual Studio xxxx\Visualizers。
使用 VS 进行调试时,对于 DataSet
、DataTable
、DataRow
和 DataView
对象,有一个额外的可视化工具选项。
关注点
出于某种原因,数组不允许在 Visual Studio 调试中进行可视化,但当使用 VisualizerDevelopmentHost
类来测试可视化工具时,数组是允许的。
本项目展示了一个变通方法,可以使不可序列化的对象可用于我们的自定义可视化工具。
创建可视化工具
本项目是使用 Visual Studio Express 创建的,任何版本都可以使用。
首先创建一个类库项目,然后添加对 Visual Studio 可视化工具 API 的引用,该 DLL 可以在以下位置找到:Visual Studio 安装文件夹)\Common7\IDE\ReferenceAssemblies\v2.0 Microsoft.VisualStudio.DebuggerVisualizers.dll。
添加可视化工具将接收的对象类型的引用
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(DSVisualizer), typeof(VisualizerObjectSource),
Target = typeof(DataSet), Description = "My DataSet Visualizer")]
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(DTVisualizer), typeof(VisualizerObjectSource), Target = typeof(DataTable),
Description = "My DataTable Visualizer")]
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(DRVisualizer), typeof(DataRowVisualizerObjectSource),
Target = typeof(DataRow), Description = "My DataRow Visualizer")]
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(DVVisualizer), typeof(DataRowVisualizerObjectSource),
Target = typeof(DataView), Description = "My DataView Visualizer")]
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(DRVVisualizer), typeof(DataRowVisualizerObjectSource),
Target = typeof(DataRowView), Description = "My DataRowView Visualizer")]
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(DRCollectionVisualizer), typeof(DataRowVisualizerObjectSource),
Target = typeof(DataRowCollection), Description = "My DataRowCollection Visualizer")]
这可以位于项目中的任何 cs 文件中,但必须在任何命名空间声明之外。如您所见,某些类型使用 VisualizerObjectSource
,而其他类型使用 DataRowVisualizerObjectSource
,这是因为 DataRow
类型需要一些处理才能使用,这将在后面介绍。
将要获取要可视化对象的类必须继承自 DialogDebuggerVisualizer
。
这将允许重写 Show
方法
protected override void Show(IDialogVisualizerService windowService,
IVisualizerObjectProvider objectProvider)
objectProvider
将允许获取要可视化对象的实例
DataTable dt = objectProvider.GetObject() as DataTable;
此代码段用于数据表可视化工具。我遵循的规则是每个对象类型一个类。
windowService
是向用户显示窗体或用户控件的内容
DialogResult dr = windowService.ShowDialog(mainForm);
mainForm
是一个使用 dt
对象初始化的窗体实例。现在我们可以将其绑定到 DataGridView
,以便用户可以查看数据。
数据行
如前所述,数据行类型不能按原样使用,因为它没有实现 ISerializable
接口。那么我们该如何使用它呢?
要获取 dataRow
,我们必须创建一个自定义 VisualizerObjectSource
,因此我们创建 DataRowVisualizerObjectSource
,它继承自 VisualizerObjectSource
,现在我们可以重写 GetData
方法
public override void GetData(object target, Stream outgoingData)
{
if (target != null)
{
if (target is DataRow)
{
DataRow row = target as DataRow;
DataTable table;
if (row.Table == null)
{
table = new DataTable("DataRowDebuggerTableObjectSource");
for (int i = 0; i < row.ItemArray.Length; i++)
{
table.Columns.Add(string.Format("Col{o}", i.ToString()), typeof(string));
}
}
else
{
table = row.Table.Clone();
}
table.LoadDataRow(row.ItemArray, true);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(outgoingData, table);
}
诀窍是将数据行包装在数据表中,因为数据表实现了 ISerializable
接口。
所以现在我们已经包装了数据行,我们可以简单地调用
DataTable dt = objectProvider.GetObject() as DataTable;
在我们自定义的 debuggerVisualizer DRVisualizer 中,并将其传递给 mainForm
。
使可视化工具准备好进行编辑
如果对象是可编辑的,我们可以使可视化工具将用户在可视化工具中所做的更改刷新到 Visual Studio 中正在调试的对象。
objectProvider
可以告诉我们对象是否可编辑,在变量 objectProvider.IsObjectReplaceable
中,因此我们可以用已更改的对象替换它
DialogResult dr = windowService.ShowDialog(main);
if (objectProvider.IsObjectReplaceable && dr == DialogResult.OK)
objectProvider.ReplaceObject(ds);
ReplaceObject
方法是可用于将更改持久化到调试变量的方法之一,这些方法是:ReplaceData()
、ReplaceObject()
、TransferData()
和 TransferObject()
。
MSDN 文档关于这些方法
“使用 Replace 方法之一会在调试器中创建一个新的数据对象,该对象将替换正在可视化的对象。如果要更改原始对象的内容而不替换它,请使用 Transfer 方法之一。”
TransferObject()
和 ReplaceObject()
方法发送正在可视化的对象,但对象必须实现 ISerializable
。
TransferData()
和 ReplaceData()
方法用于我们需要实现自定义序列化时,这些方法接收一个流,在我们的自定义 VisualizerObjectSource
中,我们可以重写 ReplaceData()
或 TransferData()
。
因此,在可视化工具中的 DataRow
的情况下,我们有
if (objectProvider.IsObjectReplaceable && dr == DialogResult.OK)
{
//DataRow is not serializable, so we serialize the item array,
//in the TransferData override of the DataRowVisualizerObjectSource we deserialize the
//itemArray and update the values od the original DataRow
objectProvider.TransferData(StreamSerializer.ObjectToStream(null, dt.Rows[0].ItemArray));
}
StreamSerializer.ObjectToStream
是一个辅助函数,它接收一个对象并创建一个流,在这种情况下是 DataRow 的 itemArray,但它也可以是一个包含该数据行的 datatable。
public static Stream ObjectToStream(Stream outgoingData, object data)
{
if (outgoingData == null)
outgoingData = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(outgoingData, data);
return outgoingData;
}
因此,在我们的自定义 VisualizerObjectSource
中,我们可以重写 TransferData()
方法并更新已更改的值
public override void TransferData(object target, Stream incomingData, Stream outgoingData)
{
if (target is DataRow)
{
DataRow row = target as DataRow;
var itemArray = StreamSerializer.StreamToObject(incomingData) as object[];
//the first column was added on the visualizer form, is the status column
for (int i = 1; i < itemArray.Length; i++)
{
if (!(target as DataRow).Table.Columns[i - 1].ReadOnly &&
!CompareData.Compare(row, itemArray, i - 1, i))
row[i - 1] = itemArray[i];
}
}
目标是原始对象,因此更改它将把更改传递给用户正在调试的变量。
测试可视化工具
为了测试可视化工具,我们必须在自定义可视化对象中创建一个公共方法,例如测试数据集可视化工具
public static void TestShowVisualizer(object objectToVisualize)
{
VisualizerDevelopmentHost visualizerHost =
new VisualizerDevelopmentHost(objectToVisualize, typeof(DSVisualizer));
visualizerHost.ShowVisualizer();
}
VisualizerDevelopmentHost
对象构造函数有三个重载,上面的重载适用于简单的可视化工具,如果我们必须使用自定义 VisualizerObjectSource
,就像在 DataRow
可视化工具中使用的那样,我们有
public static void TestShowVisualizer(object objectToVisualize)
{
VisualizerDevelopmentHost visualizerHost =
new VisualizerDevelopmentHost(objectToVisualize,
typeof(DRVisualizer), typeof(DataRowVisualizerObjectSource));
visualizerHost.ShowVisualizer();
}
这里的第三个参数是 VisualizerObjectSource
类型。还有一个重载,我们可以在其中定义 objectToVisualize
是只读还是非只读。
我没有设法使用 TestShowVisualizer
测试 ReplaceObject
,在 VS 中调试并传递给测试方法的 dataset 从未更新。这仅在使用编译后的 DLL 并将其放置在 VS visualizers 文件夹中时才有效。
在 VS 中使用可视化工具
要在 Visual Studio(2010 或 2012)中使用可视化工具,请参阅“使用代码”。
当在调试中观察变量时,有一个放大镜允许您选择注册到该类型变量的多个可视化工具。
如果 DLL 在正确的位置,应该有两个 dataset
可视化工具,一个是 Visual Studio 自带的,一个是我们的。
选择 FR DataSet Visualizer 将打开可视化工具
在这里,我们可以在树视图中看到所有数据表,并在网格视图中看到所选数据表的数据。
将鼠标悬停在单元格上,我们可以看到更多信息
在属性选项卡上,我们可以看到树视图中选定对象的所有属性
在选项选项卡上,我们可以过滤可见的列或显示的数据,要过滤列,我们可以只显示包含某些字符串的列,用“;”分隔
或者我们可以隐藏包含某些字符串的列,用“;”分隔
要过滤数据,我们可以设置绑定源过滤器字符串
还有一个包含更多选项的菜单,例如接受或拒绝更改(如果对象可编辑)。我们还可以查看估计的数据大小
此项目有一个选项可以将数据导出到 Excel 文件,这是使用 EPPlus 库完成的。
历史
- 2013-04-17:当前支持 Visual Studio 2010 和 Visual Studio 2012。
- 2013-04-24:测试和使用可视化工具。
- 2013-04-25:持久化未实现
ISerializable
的对象的更改。 - 2013-06-10:链接已更新。