·用于编写单元测试的 NUnit
·用于创建代码文档资料的 NDoc
·用于生成解决方案的 NAnt
·用于生成代码的 CodeSmith
·用于监视代码的 FxCop
·用于编译少量代码的 Snippet Compiler
·两种不同的转换器工具ASPNET 版本转换器和 Visual Studio NET 项目转换器
·用于生成正则表达式的 Regulator
·用于分析程序集的 NET Reflector
本文使用了下列技术
NETC# 或 Visual Basic NETVisual Studio NET
除非您使用能够获得的最佳工具否则您无法期望生成一流的应用程序除了像 Visual Studio®NET 这样的着名工具以外还可以从 NET 社区获得许多小型的不太为人所知的工具在本文中我将向您介绍一些目前可以获得的面向 NET 开发的最佳免费工具我将引导您完成一个有关如何使用其中每种工具的快速教程 — 一些工具在许多时候可以使您节约一分钟而另一些工具则可能彻底改变您编写代码的方式因为我要在本篇文章中介绍如此之多的不同工具所以我无法详尽讨论其中每种工具但您应该了解到有关每种工具的足够信息以便判断哪些工具对您的项目有用
Snippet Compiler
Snippet Compiler 是一个基于 Windows® 的小型应用程序您可以通过它来编写编译和运行代码如果您具有较小的代码段并且您不希望为其创建完整的 Visual Studio NET 项目(以及伴随该项目的所有文件)则该工具将很有用
例如假设我希望向您说明如何从 Microsoft?NET 框架中启动另一个应用程序在 Snippet Compiler 中我将通过新建一个能够创建小型控制台应用程序的文件开始可以在该控制台应用程序的 Main 方法内部创建代码片段而这正是我要在这里做的事情下面的代码片段演示了如何从 NET 框架中创建记事本实例
SystemDiagnosticsProcess proc = new SystemDiagnosticsProcess();
procStartInfoFileName= notepadexe;
procStart();
procWaitForExit();
当然该代码片段本身无法编译而这正是 Snippet Compiler 的用武之地图 显示了 Snippet Compiler 中的这一代码示例
图 Snippet Compiler
要测试该代码片段只须按 play(运行)按钮(绿色三角形)它就会在调试模式下运行该代码片段将生成一个弹出式控制台应用程序并且将显示记事本当您关闭记事本时该控制台应用程序也将关闭
就我个人而言我是在尝试为某位向我求助的人士创建一个小型示例时才发现 Snippet Compiler 是如此宝贵的 — 如果不使用该工具则我通常必须新建一个项目确保每个部分都能编译通过然后将代码片段发送给求助者并删除该项目Snippet Compiler 使得这一过程变得更加容易更加愉快
Snippet Compiler 由 Jeff Key 编写并且可以从 下载
Regulator
Regulator 是最后一个添加到我的头等工具清单中的它是一种很有特色的工具能够使生成和测试正则表达式变得很容易人们对正则表达式重新产生了兴趣因为它们在 NET 框架中受到很好的支持正则表达式用来基于字符频率和字符顺序定义字符串中的模式它们最常见的用途是作为验证用户输入有效性的手段或者作为在较大字符串中查找字符串的方法 — 例如在 Web 页上查找 URL 或电子邮件地址
Regulator 使您可以输入一个正则表达式以及一些针对其运行该表达式的输入内容这样在应用程序中实现该正则表达式之前您可以了解它将产生什么效果以及它将返回哪些种类的匹配项图 显示了带有简单正则表达式的 Regulator
图
文档中包含该正则表达式 — 在该示例中它是 []*应该匹配一行中任意数量的数字右下侧的框中含有针对该正则表达式的输入而左下侧的框显示了该正则表达式在输入内容中找到的匹配项在这样的单独应用程序中编写和测试正则表达式要比尝试在您的应用程序中处理它们容易得多
Regulator 中的最佳功能之一是能够在 搜索联机正则表达式库例如如果您在搜索框中输入字符串phone您将找到 种以上能够匹配各种电话号码的不同的正则表达式包括用于英国澳大利亚的表达式以及其他许多电话号码Regulator 由 Roy Osherove 编写并且可以在 /regulator 下载
CodeSmith
CodeSmith 是一种基于模板的代码生成工具它使用类似于 ASPNET 的语法来生成任意类型的代码或文本与其他许多代码生成工具不同CodeSmith 不要求您订阅特定的应用程序设计或体系结构使用 CodeSmith可以生成包括简单的强类型集合和完整应用程序在内的任何东西
当您生成应用程序时您经常需要重复完成某些特定的任务例如编写数据访问代码或者生成自定义集合CodeSmith 在这些时候特别有用因为您可以编写模板自动完成这些任务从而不仅提高您的工作效率而且能够自动完成那些最为乏味的任务CodeSmith 附带了许多模板包括对应于所有 NET 集合类型的模板以及用于生成存储过程的模板但该工具的真正威力在于能够创建自定义模板为了使您能够入门我将快速介绍一下如何生成自定义模板
生成自定义模板
CodeSmith 模板只是一些可以在任意文本编辑器中创建的文本文件它们的唯一要求是用 cst 文件扩展名来保存它们我将要生成的示例模板将接受一个字符串然后基于该字符串生成一个类创建模板的第一步是添加模板头它可声明模板的语言目标语言以及简要模板说明
<%@ CodeTemplate Language=C#
TargetLanguage=C#
Description=Car Template %>
模板的下一部分是属性声明在这里可声明将在模板每次运行时指定的属性就该模板而言我要使用的唯一属性只是一个字符串因此属性声明如下所示
<%@ Property Name=ClassName Type=String Category=Context
Description=Class Name %>
该属性声明将使 ClassName 属性出现在 CodeSmith 属性窗口中以便可以在模板运行时指定它下一步是实际生成模板主体它非常类似于用 ASPNET 进行编码以下是该模板的主体
Custom Template
public sealed class <%= ClassName %>
{
private static volatile <%= ClassName %> _instance;
private <%= ClassName %>() {}
private static readonly object _syncRoot = new object();
public static <%= ClassName %> Value
{
get
{
if (_instance == null)
{
lock(_syncRoot)
{
if (_instance == null)
{
_instance = new <%= ClassName %>();
}
}
}
return _instance;
}
}
}
SingletonClass public sealed class SingletonClass {
private static volatile SingletonClass _instance;
private SingletonClass()
{
}
private static readonly object _syncRoot = new object();
public static SingletonClass Value
{
get
{
if (_instance == null)
{
lock(_syncRoot)
{
if (_instance == null)
{
_instance = new SingletonClass();
}
}
}
return _instance;
}
}
}
正如您所见该模板接受字符串输入并使用该类名生成单独的类在模板主体中使用与 ASPNET 中相同的起始和结束标记在该模板中我只是插入属性值但您还可以在这些标记内部使用任意类型的 NET 代码在该模板完成之后您就可以通过双击它或者从 CodeSmith 应用程序中打开它将其加载到 CodeSmith 中图 显示了已经加载到 CodeSmith 中的该模板
图
您可以看到左侧的属性正是我在该模板中声明的属性如果我输入SingletonClass作为类名并单击 Generate 按钮则将生成模板代码底部显示的类
CodeSmith 使用起来相当容易如果能够正确应用则可以产生一些令人难以置信的结果面向代码生成的应用程序中最常见的部分之一是数据访问层CodeSmith 包括一个名为 SchemaExplorer 的特殊的程序集可用来从表存储过程或几乎任何其他 SQL Server? 对象生成模板
CodeSmith 由 Eric J Smith 编写并且可以在 下载
NUnit
NUnit 是为 NET 框架生成的开放源代码单元测试框架NUnit 使您可以用您喜欢的语言编写测试从而测试应用程序的特定功能当您首次编写代码时单元测试是一种测试代码功能的很好方法它还提供了一种对应用程序进行回归测试的方法NUnit 应用程序提供了一个用于编写单元测试的框架以及一个运行这些测试和查看结果的图形界面
编写 NUnit 测试
作为示例我将测试 NET 框架中 Hashtable 类的功能以确定是否可以添加两个对象并且随后检索这些对象我的第一步是添加对 NUnitFramework 程序集的引用该程序集将赋予我对 NUnit 框架的属性和方法的访问权接下来我将创建一个类并用 TestFixture 属性标记它该属性使 NUnit 可以知道该类包含 NUnit 测试
using System;
using SystemCollections;
using NUnitFramework;
namespace NUnitExample
{
[TestFixture]
public class HashtableTest {
public HashtableTest() {
}
}
}
下一步我将创建一个方法并用 [Test] 属性标记它以便 NUnit 知道该方法是一个测试然后我将建立一个 Hashtable 并向其添加两个值再使用 AssertAreEqual 方法查看我是否可以检索到与我添加到 Hashtable 的值相同的值如下面的代码所示
[Test]
public void HashtableAddTest()
{
Hashtable ht = new Hashtable();
htAdd(Key Value);
htAdd(Key Value);
AssertAreEqual(Value ht[Key] Wrong object returned!);
AssertAreEqual(Value ht[Key] Wrong object returned!);
}
这将确认我可以首先向 Hashtable 中添加值并随后检索相应的值 — 这是一个很简单的测试但能够表现 NUnit 的功能存在许多测试类型以及各种 Assert 方法可使用它们来测试代码的每个部分
要运行该测试我需要生成项目在 NUnit 应用程序中打开生成的程序集然后单击 Run 按钮图 显示了结果当我看到那个大的绿色条纹时我有一种兴奋和头晕的感觉因为它让我知道测试已经通过了这个简单的示例表明 NUnit 和单元测试是多么方便和强大由于能够编写可以保存的单元测试并且每当您更改代码时都可以重新运行该单元测试您不仅可以更容易地检测到代码中的缺陷而且最终能够交付更好的应用程序
图 NUnit
NUnit 是一个开放源代码项目并且可以从 下载还有一个优秀的 NUnit Visual Studio NET 外接程序它使您可以直接从 Visual Studio 中运行单元测试您可以在 找到它有关 NUnit 及其在测试驱动开发中的地位的详细信息请参阅文章TestDriven C#: Improve the Design and Flexibility of Your Project with Extreme Programming Techniques(MSDN ®Magazine 年 月刊)
FxCop
NET 框架非常强大这意味着存在创建优秀应用程序的极大可能但是也同样存在创建劣质程序的可能FxCop 是有助于创建更好的应用程序的工具之一它所采用的方法是使您能够分析程序集并使用一些不同的规则来检查它是否符合这些规则FxCop 随附了由 Microsoft 创建的固定数量的规则但您也可以创建并包括您自己的规则例如如果您决定所有的类都应该具有一个不带任何参数的默认构造函数则可以编写一条规则以确保程序集的每个类上都具有一个构造函数这样无论是谁编写该代码您都将获得一定程度的一致性如果您需要有关创建自定义规则的详细信息请参阅 John Robbins 的有关该主题的 Bugslayer 专栏文章(MSDN ® Magazine 年 月刊)
那么让我们观察一下实际运行的 FxCop并且看一下它在我一直在处理的 NUnitExample 程序集中找到哪些错误当您打开 FxCop 时您首先需要创建一个 FxCop 项目然后向其添加您要测试的程序集在将该程序集添加到项目以后就可以按 AnalyzeFxCop 将分析该程序集图 中显示了在该程序集中找到的错误和警告
图
FxCop 在我的程序集中找到了几个问题您可以双击某个错误以查看详细信息包括规则说明以及在哪里可以找到更多信息(您可以做的一件有趣的事情是在框架程序集上运行 FxCop 并查看发生了什么事情)
FxCop 可以帮助您创建更好的更一致的代码但它无法补偿低劣的应用程序设计或非常简单拙劣的编程FxCop 也不能替代对等代码检查但是因为它可以在进行代码检查之前捕获大量错误所以您可以花费更多时间来解决严重的问题而不必担心命名约定FxCop 由 Microsoft 开发并且可以从 下载
Lutz Roeder 的 NET Reflector
下一个必不可少的工具称为 NET Reflector它是一个类浏览器和反编译器可以分析程序集并向您展示它的所有秘密NET 框架向全世界引入了可用来分析任何基于 NET 的代码(无论它是单个类还是完整的程序集)的反射概念反射还可以用来检索有关特定程序集中包含的各种类方法和属性的信息使用 NET Reflector您可以浏览程序集的类和方法可以分析由这些类和方法生成的 Microsoft 中间语言 (MSIL)并且可以反编译这些类和方法并查看 C# 或 Visual Basic ®NET 中的等价类和方法
为了演示 NET Reflector 的工作方式我将加载和分析前面已经显示的 NUnitExample 程序集图 显示了 NET Reflector 中加载的该程序集
图 NUnitExample 程序集
在 NET Reflector 内部有各种可用来进一步分析该程序集的工具要查看构成某个方法的 MSIL请单击该方法并从菜单中选择 Disassembler
除了能够查看 MSIL 以外您还可以通过选择 Tools 菜单下的 Decompiler 来查看该方法的 C# 形式通过在 Languages 菜单下更改您的选择您还可以查看该方法被反编译到 Visual Basic NET 或 Delphi 以后的形式以下为 NET Reflector 生成的代码
public void HashtableAddTest()
{
Hashtable hashtable;
hashtable = new Hashtable();
hashtableAdd(Key Value);
hashtableAdd(Key Value);
AssertAreEqual(Value hashtable[Key]
Wrong object returned!);
AssertAreEqual(Value hashtable[Key]
Wrong object returned!);
}
前面的代码看起来非常像我为该方法实际编写的代码以下为该程序集中的实际代码
public void HashtableAddTest()
{
Hashtable ht = new Hashtable();
htAdd(Key Value);
htAdd(Key Value);
AssertAreEqual(Value ht[Key] Wrong object returned!);
AssertAreEqual(Value ht[Key] Wrong object returned!);
}
尽管上述代码中存在一些小的差异但它们在功能上是完全相同的
虽然该示例是一种显示实际代码与反编译代码之间对比的好方法但在我看来它并不代表 NET Reflector 所具有的最佳用途 — 分析 NET 框架程序集和方法NET 框架提供了许多执行类似操作的不同方法例如如果您需要从 XML 中读取一组数据则存在多种使用 XmlDocumentXPathNavigator 或 XmlReader 完成该工作的不同方法通过使用 NET Reflector您可以查看 Microsoft 在编写数据集的 ReadXml 方法时使用了什么或者查看他们在从配置文件读取数据时做了哪些工作NET Reflector 还是一个了解以下最佳实施策略的优秀方法创建诸如 HttpHandlers 或配置处理程序之类的对象因为您可以了解到 Microsoft 工作组实际上是如何在框架中生成这些对象的
NET Reflector 由 Lutz Roeder 编写并且可以从 下载
NDoc
编写代码文档资料几乎总是一项令人畏惧的任务我所说的不是早期设计文档甚至也不是更为详细的设计文档我说的是记录类上的各个方法和属性NDoc 工具能够使用反射来分析程序集并使用从 C# XML 注释生成的 XML 自动为代码生成文档资料XML 注释仅适用于 C#但有一个名为 VBCommenter 的 Visual Studio NET Power Toy它能够为 Visual Basic NET 完成类似的工作此外下一版本的 Visual Studio 将为更多语言支持 XML 注释
使用 NDoc 时您仍然在编写代码的技术文档但您是在编写代码的过程中完成了文档编写工作(在 XML 注释中)而这更容易忍受使用 NDoc 时第一步是为您的程序集打开 XML 注释生成功能右键单击该项目并选择 Properties | Configuration Properties | Build然后在 XML Documentation File 选项中输入用于保存 XML 文件的路径当该项目生成时将创建一个 XML 文件其中包含所有 XML 注释下面是 NUnit 示例中的一个用 XML 编写了文档的方法
/// <summary>
/// This test adds a number of values to the Hashtable collection
/// and then retrieves those values and checks if they match
/// </summary>
[Test]
public void HashtableAddTest()
{
//Method Body Here
}
有关该方法的 XML 文档资料将被提取并保存在 XML 文件中如下所示
<member name=M:NUnitExampleHashtableTestHashtableAddTest>
<summary>This test adds a number of values to the Hashtable collection
and then retrieves those values and checks if they match</summary>
</member>
NDoc 使用反射来考察您的程序集然后读取该文档中的 XML并且将它们进行匹配NDoc 使用该数据来创建任意数量的不同文档格式包括 HTML 帮助文件 (CHM)在生成 XML 文件以后下一步是将程序集和 XML 文件加载到 NDoc 中以便可以对它们进行处理通过打开 NDoc 并单击 Add 按钮可以容易地完成该工作
在将程序集和 XML 文件加载到 NDoc 中并且使用可用的属性范围自定义输出以后单击 Generate 按钮将启动生成文档资料的过程使用默认的属性NDoc 可以生成一些非常吸引人并且实用的l 和 chm 文件从而以快速有效的方式自动完成原来非常乏味的任务
NDoc 是一个开放源代码项目并且可以从 下载
NAnt
NAnt 是一个基于 NET 的生成工具与当前版本的 Visual Studio NET 不同它使得为您的项目创建生成过程变得非常容易当您拥有大量从事单个项目的开发人员时您不能依赖于从单个用户的座位进行生成您也不希望必须定期手动生成该项目您更愿意创建每天晚上运行的自动生成过程NAnt 使您可以生成解决方案复制文件运行 NUnit 测试发送电子邮件等等遗憾的是NAnt 缺少漂亮的图形界面但它的确具有可以指定应该在生成过程中完成哪些任务的控制台应用程序和 XML 文件注意MSBuild(属于 Visual Studio 的新的生成平台)为每种健壮的生成方案进行了准备并且由基于 XML 的项目文件以类似的方式驱动
实际运行的 NAnt
在该示例中我将为前面创建的 NUnitExample 解决方案创建一个 NAnt 版本文件首先我需要创建一个具有 build 扩展名的 XML 文件将其放在我的项目的根目录中然后向该文件的顶部添加一个 XML 声明我需要添加到该文件的第一个标记是 project 标记
<?xml version=?>
<project name=NUnit Example default=build basedir=>
<description>The NUnit Example Project</description>
</project>
项目标记还用于设置项目名称默认目标以及基目录Description 标记用于设置该项目的简短说明
接下来我将添加 property 标记该标记可用于将设置存储到单个位置(随后可以从文件中的任意位置访问该位置)在该例中我将创建一个名为 debug 的属性我可以随后将其设置为 true 或 false以反映我是否要在调试配置下编译该项目(最后这一特定属性并未真正影响如何生成该项目它只是您设置的一个变量当您真正确定了如何生成该项目时将读取该变量)
接下来我需要创建一个 target 标记一个项目可以包含多个可在 NAnt 运行时指定的 target如果未指定 target则使用默认 target(我在 project 元素中设置的 target)在该示例中默认 target 是 build让我们观察一下 target 元素它将包含大多数生成信息
<target name=build description=compiles the source code>
</target>
在 target 元素内我将把 target 的名称设置为 build并且创建有关该 target 将做哪些工作的说明我还将创建一个 csc 元素该元素用于指定应该传递给 csc C# 编译器的数据让我们看一下该 csc 元素
<csc target=library output=\bin\debug\NUnitExampledll
debug=${debug}>
<references>
<includes name=C:\program files\NUnit V\bin\NUnitFrameworkdll/>
</references>
<sources>
<includes name=HashtableTestcs/>
</sources>
</csc>
首先我必须设置该 csc 元素的 target在该例中我将创建一个 dll 文件因此我将 target 设置为 library接下来我必须设置 csc 元素的 output它是将要创建 dll 文件的位置最后我需要设置 debug 属性它确定了是否在调试中编译该项目因为我在前面创建了一个用于存储该值的属性所以我可以使用下面的字符串来访问该属性的值${debug}Csc 元素还包含一些子元素我需要创建两个元素references 元素将告诉 NAnt 需要为该项目引用哪些程序集sources 元素告诉 NAnt 要在生成过程中包含哪些文件在该示例中我引用了 NUnitFrameworkdll 程序集并包含了 HashtableTestcs 文件以下代码中显示了完整的生成文件(您通常还要创建一个干净的 target用于删除生成的文件但为了简洁起见我已经将其省略)
<?xml version=?>
<project name=NUnit Example default=build basedir=>
<description>The NUnit Example Project</description>
<property name=debug value=true/>
<target name=build description=compiles the source code>
<csc target=library output=\bin\debug\NUnitExampledll
debug=${debug}>
<references>
<includes name=C:\program files\NUnit
V\bin\NUnitFrameworkdll />
</references>
<sources>
<includes name=HashtableTestcs/>
</sources>
</csc>
</target>
</project>
要生成该文件我需要转到我的项目的根目录(生成文件位于此处)然后从该位置执行 nantexe如果生成成功您可以在该应用程序的 bin 目录中找到 dll 和 pdb 文件尽管使用 NAnt 肯定不像在 Visual Studio 中单击 Build 那样简单但它仍然是一种非常强大的工具可用于开发按自动计划运行的生成过程NAnt 还包括一些有用的功能例如能够运行单元测试或者复制附加文件(这些功能没有受到当前 Visual Studio 生成过程的支持)
NAnt 是一个开放源代码项目并且可以从 下载
转换工具
我已经将两个独立的工具合在一起放在标题转换工具下面这两个工具都非常简单但又可能极为有用第一个工具是 ASPNET 版本转换器它可用于转换 ASPNET(虚拟目录在它下面运行)的版本第二个工具是 Visual Studio Converter它可用于将项目文件从 Visual Studio NET 转换到 Visual Studio NET
当 IIS 处理请求时它会查看正在请求的文件的扩展名然后基于该 Web 站点或虚拟目录的扩展名映射将请求委派给 ISAPI 扩展或者自己处理该请求这正是 ASPNET 的工作方式将为所有 ASPNET 扩展名注册扩展名映射并将这些扩展名映射导向 aspnet_isapidll这种工作方式是完美无缺的除非您安装了 ASPNET — 它会将扩展名映射升级到新版本的 aspnet_isapidll当在 ASPNET 上生成的应用程序试图用 版运行时这会导致错误要解决该问题可以将所有扩展名映射重新转换到 版的 aspnet_isapidll但是由于有 种扩展名映射所以手动完成这一工作将很枯燥这正是 ASPNET 版本转换器可以发挥作用的时候使用这一小型实用工具可以转换任何单个 ASPNET 应用程序所使用的 NET 框架的版本
图 ASPNET 版本转换器
图 显示了实际运行的 ASPNET 版本转换器它的使用方法非常简单只须选择相应的应用程序然后选择您希望该应用程序使用的 NET 框架版本该工具随后将使用 aspnet_regiisexe 命令行工具将该应用程序转换到所选版本的框架随着将来版本的 ASPNET 和 NET 框架的发布该工具将变得更为有用
ASPNET 版本转换器由 Denis Bauer 编写并且可以从 下载
Visual Studio NET 项目转换器(参见图 )非常类似于 ASPNET 版本转换器区别在于它用于转换 Visual Studio 项目文件的版本尽管在 NET 框架的 版和 版之间只有很小的差异但一旦将项目文件从 Visual Studio NET 转换到 Visual Studio NET 将无法再把它转换回去虽然这在大多数时候可能不会成为问题(因为在 NET 框架 版和 版之间几乎没有什么破坏性的更改)但在某些时刻您可能需要将项目转换回去该转换器可以将任何解决方案或项目文件从 Visual Studio (Visual Studio NET ) 转换到 Visual Studio (Visual Studio NET )并在必要时进行反向转换
图 Visual Studio NET 项目转换器
Visual Studio NET 项目转换器由 Dacris Software 编写该工具可以从 下载