flanker base @ cnblogs

defy all challenges & accelerate your life

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Daniel Smolka 著 Yet another QuickWatch
flanker 译 in MSProject

 

简介

以前有一个项目,测试者和高级用户需要有一个工具来监视复杂的数据,这就是为什么我受Visual Studio的快速监视启发而制作这个工具。

它有一些额外特性,比如:

·只让用户看见开发者想让他看见的域/属性。
·允许给显示的成员指定一个用户友好的名称
·允许选择子树保存成XML文件

构建者

一个月前,我被要求显示一些有二十多个类的数据,每一个类有十来种成员。要用一个单一用途的代码段来显示它太复杂了,几乎不可能来维护它,因为数据结构会改变。

所以,怎样来自动处理?我使用特性(Attributes)来标记要显示的成员:

·TreeLeafNodeAttribute - 定义成员为树的叶子节点,它不能再含有子节点。通常用在字符串,数字和日期上。
·TreeInternalNode - 定义成员为树的内部节点,它包含内部节点或者叶子节点。通常用在嵌套的数据结构和集合上。

示例:

    public class Catalog
    {
        [TreeLeafNode]
        
public string name;

        [TreeInternalNode]
        
public Source source;

        [TreeInternalNode]
        
public List cds;
    }

这种对象被传递给构建者,构建者分为三个层次:

1. 底层 - 实现构建树的逻辑。
2. 中层 - 把树的内容渲染到具体的输出设备上。
3. 顶层 - 保证构建者类型安全并处理特殊情况。

构建者递归遍历传入对象的所有带标记成员。为了获得标记成员的数据结构,构建者通过System.Reflection使用TreeStructure类来提取数据结构。结果被缓存在一个静态的哈希表里,因为在程序运行期间它不会再改变。它会被构建者重复使用。

构建者会区分两种类型的内部节点:集合和其他的。如果用TreeInternalNode标记的项实现了IEnumerable接口,它就被显示为一个集合(见上图的cds节点),否则就被显示为另一种内部节点(见源代码)。如果实现了IEnumerable接口的项还实现了ICollection接口或者它是一个数组,那么项的子项数目也会被显示。内部节点被显示的文本是通过调用节点对象的ToString方法来获得的(和Visual Studio中的快速监视一样)。

BuildTitle方法格式化叶子节点的显示。字符串以省略方式显示,数字显示整数部分和小数点后两位,日期显示为日期。有一个特别的NullDateTime属性,如果日期是这个值,那么就显示为null。

如果重写了TranslateName方法,那么所有的成员可以有一个用户友好的名称。例如,成员TrxNum可以被改为Transaction number

数据输入和输出

我们从一个XML文件中并行化出分类目录,因为这是获得一些数据的最简单方法。在实际的应用程序中,通常可能从数据库或者其他数据源来获得数据。

在这个示例项目中,构建者的中层有一个额外的功能,它给所有内部节点TreeNode设置了Tag属性,如果节点被选择,用户可以把节点所有内容序列化到一个文件中,以方便后期调试或其他用途使用。

实际上,中层可以有不同的实现。在示例程序中,我使用的是标准的System.Windows.Forms.TreeView。但是我们公司使用了我们自己的基于DataSet的可视化组件。中层也可以压根不需要可视化输出,可以把输出保存到数据库或者XML文件中。

相关材料

二叉树和二叉排序树 - 原理和术语
http://msdn2.microsoft.com/en-us/library/ms379572(VS.80).aspx

用于DataSet的快速监视
http://www.codeproject.com/csharp/DSWatch.asp

把XML文件显示在TreeView上
http://www.java2s.com/Code/CSharp/XML/DisplayXMLfilecontenttoTreeView.htm

posted on 2008-01-07 11:56  flankerfc  阅读(638)  评论(0编辑  收藏  举报