65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Reflector 和 Graph 插件创建图表( 第二部分)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.27/5 (7投票s)

2009年2月23日

CPOL

6分钟阅读

viewsIcon

36058

downloadIcon

1129

现在,将对其他依赖项进行图形化显示,不再使用 Reflector。

refractor.JPG

引言

在本文中,我们将尝试生成有用的程序集图表。我主要在开发期间对程序集感兴趣,但尝试理解一个已完成的程序集是类似的任务。

上一篇文章(带反射器和图形插件的图表(第 1 部分))使用了 Reflector 作为宿主,因此有了文章的名称,但新的插件使用了一个名为 Refractor 的新宿主。所有这些都包含在下载文件中。

背景

以前,我们处理的是图形化显示一个类中哪些方法调用了其他哪些方法。类有各种形状和大小,但我们感兴趣对其进行图表化的类通常是那些难以理解的类。通常,这些包括 WinForms 类,其中事件调用公共方法生成的链接会迅速变得混乱。这是通过 Reflector 的插件实现的,效果相当不错。

这已经在我的日常工作中以几种不同的方式证明了它的实用性

  1. 在构建类的过程中,跟踪方法调用图很有用。有时,我会手动完成,但随时可用的图表意味着我更频繁地参考它。
  2. 在尝试理解他人编写的类时。通常,我拥有完整的源代码,但它可能由多人编写,并且在一段时间内,这使得它难以理解。
  3. 在审查代码时,我可以更轻松地检查异常情况,这些异常情况可能表明设计问题。

我想看看在“图表空间”中是否还有其他有用的图表。事实上,很快我就需要在修复一个大型构建过程时对程序集依赖关系进行图表化,于是我为此制作了一个类似的插件,用于显示项目中所有程序集的信息。

然而,我对宿主插件架构有一些问题。

  1. 在插件框架内进行编码更加困难,特别是针对混淆过的宿主可执行文件。
  2. 生成图表可能需要很长时间。宿主没有线程支持,所以如果我想要线程,我必须自己将它集成到插件中,这当时看起来有点令人望而生畏。
  3. 我非常厌倦于点击刷新并重新选择我要图表化的项。如果宿主能够检查文件更新并重新加载,那就更好了。大多数人使用 Reflector 来检查他们没有源代码的程序集,所以程序集不会改变。当你开发一个程序集时,它会一直变化。这表明了宿主用户的一种不同风格。
  4. 我通常不关心模块或资源,而宿主树由于包含这些有时至关重要的信息而更加混乱。
  5. 我对反汇编不感兴趣,而反汇编是宿主的主要功能。话虽如此,有时拥有它还是不错的,而且我已经将一个反汇编查看器集成到了当前的宿主中。但没有反编译器!
  6. Lutz 对我将 Reflector 与插件捆绑在一起表示不满,这是可以理解的,但这使得我无法提供完整的可运行下载。

因此,有了新的宿主。

图表

继第一篇文章中的 ClassMethods 图之后,我们还有三个图表

  1. AssemblyNamespaces:这个图表对我来说不太有用,因为我处理的大多数程序集只包含一个命名空间,尽管它可以很好地显示例外情况。
  2. NamespaceClasses:这个图表很有用,尤其是在发现循环依赖关系以及显示命名空间级别的复杂性时。划分过多,则信息量不大;划分过少,则信息量过大。
  3. AssemblyClasses:这个图表通常范围太广,显示了太多不相关的功能,因此不够有用。也许,对于具有过多命名空间的小型程序集可能有用。

除了项的“内部”链接(即,包含在某个项内的所有项)之外,我们还可以查看“外部”链接,即使用某个项或被某个项使用的所有项。概念上,这些有一个“中心”节点,然后向左是传入依赖项,向右是传出依赖项,或者在两者之间。这通常可以形成一个双扇形,因此我称它们为“蝴蝶”图来区分它们。

蝴蝶图更难生成,因为要发现左侧需要搜索任何可能使用该项的内容。这相当于“grep”代码,搜索所有源代码以查找与某个项匹配的内容,这是普通开发人员*经常*做的事情。但是,也有一个好处,那就是我们只关心作为宿主项目一部分打开的文件。

  1. AssemblyButterfly
  2. 虽然我们已经有一个针对 *AllAssemblies* 的插件,但对于大型项目来说,要针对单个程序集查看可能很困难,或者生成速度很慢。它显示了某个程序集使用的程序集(正如 Visual Studio 那样),但也显示了所有使用该程序集(项目内)的程序集。我在构建和维护过程中发现它很有用。

  3. ClassButterfly
  4. 这个图表告诉我们继承了谁,实现了谁,谁继承或实现了我们,我们直接以功能方式使用的任何类,以及直接以功能方式使用我们的任何类。这与 ClassMethod 图表结合使用非常有用——打开两者并选择一个类,您就可以并排看到内部视图和外部视图。这也是一种有趣的导航代码的方式。如果我能相信它找到了所有可能的依赖关系,并且能够跳转到代码行,那么它将更有用,可以替代一些“grep”操作。

  5. MethodButterfly
  6. 所有可能调用中心方法的其他方法,以及这个方法调用的所有其他方法。同样,这可以带来有趣的导航代码体验。

GLEE 查看器控件

它在布局连接图方面做得非常出色,只需很少的用户输入。曲线绘制效果很棒。然而,控件的实现却不那么好,并且必须在 UI 线程上运行的 UI 更新部分足够大,以至于在大型图表上导致冻结。

我真的很希望对图表有更多的灵活性——例如,能够移动节点。即使是隐藏它们也证明是一场噩梦。它对孤立节点的放置很糟糕。遗憾的是,自 2006 年以来,它就没有在 MS 网站上更新过,所以我认为它短期内不会再更新了。我花了一些时间研究布局算法,并可能在不久的将来尝试更换查看器——插件与图表实现是隔离的。

使用代码

整个软件包相当大,包括用于对接、树控件等的库 DLL。如果您使用过 Reflector,您应该不会对 UI 感到困惑。没有安装程序——解压缩后会生成 *run* 文件夹,准备好放到程序文件或其他位置,如果您决定保留它的话。图表插件的源代码也包含在内,您应该能够打开项目并点击运行。或者,只需运行 *bin* 文件夹中的 exe 文件,然后将一些 DLL/exe 文件拖放到项目窗口中。

请牢记,此代码仍处于原型阶段,并且可能出于某种原因缺少某些类型的依赖关系。它应该用作指南,而不是最终参考。

© . All rights reserved.