每個(gè).Net開(kāi)發(fā)人員應(yīng)該下載的10種必備工具
發(fā)表時(shí)間:2023-08-16 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]本文討論: 用于編寫(xiě)單元測(cè)試的 NUnit 用于創(chuàng)建代碼文檔資料的 NDoc 用于生成解決方案的 NAnt 用于生成代碼的 CodeSmith 用于監(jiān)視代碼的 FxCop 用于編譯少量代碼...
本文討論:
• 用于編寫(xiě)單元測(cè)試的 NUnit
• 用于創(chuàng)建代碼文檔資料的 NDoc
• 用于生成解決方案的 NAnt
• 用于生成代碼的 CodeSmith
• 用于監(jiān)視代碼的 FxCop
• 用于編譯少量代碼的 Snippet Compiler
• 兩種不同的轉(zhuǎn)換器工具:ASP.NET 版本轉(zhuǎn)換器和 Visual Studio .NET 項(xiàng)目轉(zhuǎn)換器
• 用于生成正則表達(dá)式的 Regulator
• 用于分析程序集的 .NET Reflector
本文使用了下列技術(shù):
.NET、C# 或 Visual Basic .NET、Visual Studio .NET
除非您使用能夠獲得的最佳工具,否則您無(wú)法期望生成一流的應(yīng)用程序。除了像 Visual Studio®.NET 這樣的著名工具以外,還可以從 .NET 社區(qū)獲得許多小型的、不太為人所知的工具。在本文中,我將向您介紹一些目前可以獲得的、面向 .NET 開(kāi)發(fā)的最佳免費(fèi)工具。我將引導(dǎo)您完成一個(gè)有關(guān)如何使用其中每種工具的快速教程 — 一些工具在許多時(shí)候可以使您節(jié)約一分鐘,而另一些工具則可能徹底改變您編寫(xiě)代碼的方式。因?yàn)槲乙诒酒恼轮薪榻B如此之多的不同工具,所以我無(wú)法詳盡討論其中每種工具,但您應(yīng)該了解到有關(guān)每種工具的足夠信息,以便判斷哪些工具對(duì)您的項(xiàng)目有用。
Snippet Compiler
Snippet Compiler 是一個(gè)基于 Windows® 的小型應(yīng)用程序,您可以通過(guò)它來(lái)編寫(xiě)、編譯和運(yùn)行代碼。如果您具有較小的代碼段,并且您不希望為其創(chuàng)建完整的 Visual Studio .NET 項(xiàng)目(以及伴隨該項(xiàng)目的所有文件),則該工具將很有用。
例如,假設(shè)我希望向您說(shuō)明如何從 Microsoft?.NET 框架中啟動(dòng)另一個(gè)應(yīng)用程序。在 Snippet Compiler 中,我將通過(guò)新建一個(gè)能夠創(chuàng)建小型控制臺(tái)應(yīng)用程序的文件開(kāi)始?梢栽谠摽刂婆_(tái)應(yīng)用程序的 Main 方法內(nèi)部創(chuàng)建代碼片段,而這正是我要在這里做的事情。下面的代碼片段演示了如何從 .NET 框架中創(chuàng)建記事本實(shí)例:
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName= "notepad.exe";
proc.Start();
proc.WaitForExit();
當(dāng)然該代碼片段本身無(wú)法編譯,而這正是 Snippet Compiler 的用武之地。圖 1 顯示了 Snippet Compiler 中的這一代碼示例。
圖 1 Snippet Compiler
要測(cè)試該代碼片段,只須按 play(運(yùn)行)按鈕(綠色三角形),它就會(huì)在調(diào)試模式下運(yùn)行。該代碼片段將生成一個(gè)彈出式控制臺(tái)應(yīng)用程序,并且將顯示記事本。當(dāng)您關(guān)閉記事本時(shí),該控制臺(tái)應(yīng)用程序也將關(guān)閉。
就我個(gè)人而言,我是在嘗試為某位向我求助的人士創(chuàng)建一個(gè)小型示例時(shí),才發(fā)現(xiàn) Snippet Compiler 是如此寶貴的 — 如果不使用該工具,則我通常必須新建一個(gè)項(xiàng)目,確保每個(gè)部分都能編譯通過(guò),然后將代碼片段發(fā)送給求助者,并刪除該項(xiàng)目。Snippet Compiler 使得這一過(guò)程變得更加容易、更加愉快。
Snippet Compiler 由 Jeff Key 編寫(xiě),并且可以從 http://www.sliver.com/dotnet/SnippetCompiler 下載。
Regulator
Regulator 是最后一個(gè)添加到我的頭等工具清單中的。它是一種很有特色的工具,能夠使生成和測(cè)試正則表達(dá)式變得很容易。人們對(duì)正則表達(dá)式重新產(chǎn)生了興趣,因?yàn)樗鼈冊(cè)?.NET 框架中受到很好的支持。正則表達(dá)式用來(lái)基于字符、頻率和字符順序定義字符串中的模式。它們最常見(jiàn)的用途是作為驗(yàn)證用戶(hù)輸入有效性的手段或者作為在較大字符串中查找字符串的方法 — 例如,在 Web 頁(yè)上查找 URL 或電子郵件地址。
Regulator 使您可以輸入一個(gè)正則表達(dá)式以及一些針對(duì)其運(yùn)行該表達(dá)式的輸入內(nèi)容。這樣,在應(yīng)用程序中實(shí)現(xiàn)該正則表達(dá)式之前,您可以了解它將產(chǎn)生什么效果以及它將返回哪些種類(lèi)的匹配項(xiàng)。圖 2 顯示了帶有簡(jiǎn)單正則表達(dá)式的 Regulator。
圖 2
文檔中包含該正則表達(dá)式 — 在該示例中,它是 [0-9]*,應(yīng)該匹配一行中任意數(shù)量的數(shù)字。右下側(cè)的框中含有針對(duì)該正則表達(dá)式的輸入,而左下側(cè)的框顯示了該正則表達(dá)式在輸入內(nèi)容中找到的匹配項(xiàng)。在這樣的單獨(dú)應(yīng)用程序中編寫(xiě)和測(cè)試正則表達(dá)式,要比嘗試在您的應(yīng)用程序中處理它們?nèi)菀椎枚唷?br>
Regulator 中的最佳功能之一是能夠在 regexlib.com 搜索聯(lián)機(jī)正則表達(dá)式庫(kù)。例如,如果您在搜索框中輸入字符串“phone”,您將找到 20 種以上能夠匹配各種電話號(hào)碼的不同的正則表達(dá)式,包括用于英國(guó)、澳大利亞的表達(dá)式以及其他許多電話號(hào)碼。Regulator 由 Roy Osherove 編寫(xiě),并且可以在 http://royo.is-a-geek.com/regulator 下載。
CodeSmith
CodeSmith 是一種基于模板的代碼生成工具,它使用類(lèi)似于 ASP.NET 的語(yǔ)法來(lái)生成任意類(lèi)型的代碼或文本。與其他許多代碼生成工具不同,CodeSmith 不要求您訂閱特定的應(yīng)用程序設(shè)計(jì)或體系結(jié)構(gòu)。使用 CodeSmith,可以生成包括簡(jiǎn)單的強(qiáng)類(lèi)型集合和完整應(yīng)用程序在內(nèi)的任何東西。
當(dāng)您生成應(yīng)用程序時(shí),您經(jīng)常需要重復(fù)完成某些特定的任務(wù),例如編寫(xiě)數(shù)據(jù)訪問(wèn)代碼或者生成自定義集合。CodeSmith 在這些時(shí)候特別有用,因?yàn)槟梢跃帉?xiě)模板自動(dòng)完成這些任務(wù),從而不僅提高您的工作效率,而且能夠自動(dòng)完成那些最為乏味的任務(wù)。CodeSmith 附帶了許多模板,包括對(duì)應(yīng)于所有 .NET 集合類(lèi)型的模板以及用于生成存儲(chǔ)過(guò)程的模板,但該工具的真正威力在于能夠創(chuàng)建自定義模板。為了使您能夠入門(mén),我將快速介紹一下如何生成自定義模板。
生成自定義模板
CodeSmith 模板只是一些可以在任意文本編輯器中創(chuàng)建的文本文件。它們的唯一要求是用 .cst 文件擴(kuò)展名來(lái)保存它們。我將要生成的示例模板將接受一個(gè)字符串,然后基于該字符串生成一個(gè)類(lèi)。創(chuàng)建模板的第一步是添加模板頭,它可聲明模板的語(yǔ)言、目標(biāo)語(yǔ)言以及簡(jiǎn)要模板說(shuō)明:
<%@ CodeTemplate Language="C#"
TargetLanguage="C#"
Description="Car Template" %>
模板的下一部分是屬性聲明,在這里可聲明將在模板每次運(yùn)行時(shí)指定的屬性。就該模板而言,我要使用的唯一屬性只是一個(gè)字符串,因此屬性聲明如下所示:
<%@ Property Name="ClassName" Type="String" Category="Context"
Description="Class Name" %>
該屬性聲明將使 ClassName 屬性出現(xiàn)在 CodeSmith 屬性窗口中,以便可以在模板運(yùn)行時(shí)指定它。下一步是實(shí)際生成模板主體,它非常類(lèi)似于用 ASP.NET 進(jìn)行編碼。以下是該模板的主體:
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;
}
}
}
正如您所見(jiàn),該模板接受字符串輸入并使用該類(lèi)名生成單獨(dú)的類(lèi)。在模板主體中,使用與 ASP.NET 中相同的起始和結(jié)束標(biāo)記。在該模板中,我只是插入屬性值,但您還可以在這些標(biāo)記內(nèi)部使用任意類(lèi)型的 .NET 代碼。在該模板完成之后,您就可以通過(guò)雙擊它或者從 CodeSmith 應(yīng)用程序中打開(kāi)它將其加載到 CodeSmith 中。圖 4 顯示了已經(jīng)加載到 CodeSmith 中的該模板。
圖 4
您可以看到左側(cè)的屬性正是我在該模板中聲明的屬性。如果我輸入“SingletonClass”作為類(lèi)名,并單擊 Generate 按鈕,則將生成模板代碼底部顯示的類(lèi)。
CodeSmith 使用起來(lái)相當(dāng)容易,如果能夠正確應(yīng)用,則可以產(chǎn)生一些令人難以置信的結(jié)果。面向代碼生成的應(yīng)用程序中最常見(jiàn)的部分之一是數(shù)據(jù)訪問(wèn)層。CodeSmith 包括一個(gè)名為 SchemaExplorer 的特殊的程序集,可用來(lái)從表、存儲(chǔ)過(guò)程或幾乎任何其他 SQL Server? 對(duì)象生成模板。
CodeSmith 由 Eric J. Smith 編寫(xiě),并且可以在 http://www.ericjsmith.net/codesmith 下載。
NUnit
NUnit 是為 .NET 框架生成的開(kāi)放源代碼單元測(cè)試框架。NUnit 使您可以用您喜歡的語(yǔ)言編寫(xiě)測(cè)試,從而測(cè)試應(yīng)用程序的特定功能。當(dāng)您首次編寫(xiě)代碼時(shí),單元測(cè)試是一種測(cè)試代碼功能的很好方法,它還提供了一種對(duì)應(yīng)用程序進(jìn)行回歸測(cè)試的方法。NUnit 應(yīng)用程序提供了一個(gè)用于編寫(xiě)單元測(cè)試的框架,以及一個(gè)運(yùn)行這些測(cè)試和查看結(jié)果的圖形界面。
編寫(xiě) NUnit 測(cè)試
作為示例,我將測(cè)試 .NET 框架中 Hashtable 類(lèi)的功能,以確定是否可以添加兩個(gè)對(duì)象并且隨后檢索這些對(duì)象。我的第一步是添加對(duì) NUnit.Framework 程序集的引用,該程序集將賦予我對(duì) NUnit 框架的屬性和方法的訪問(wèn)權(quán)。接下來(lái),我將創(chuàng)建一個(gè)類(lèi)并用 TestFixture 屬性標(biāo)記它。該屬性使 NUnit 可以知道該類(lèi)包含 NUnit 測(cè)試:
using System;
using System.Collections;
using NUnit.Framework;
namespace NUnitExample
{
[TestFixture]
public class HashtableTest {
public HashtableTest() {
}
}
}
下一步,我將創(chuàng)建一個(gè)方法并用 [Test] 屬性標(biāo)記它,以便 NUnit 知道該方法是一個(gè)測(cè)試。然后,我將建立一個(gè) Hashtable 并向其添加兩個(gè)值,再使用 Assert.AreEqual 方法查看我是否可以檢索到與我添加到 Hashtable 的值相同的值,如下面的代碼所示:
[Test]
public void HashtableAddTest()
{
Hashtable ht = new Hashtable();
ht.Add("Key1", "Value1");
ht.Add("Key2", "Value2");
Assert.AreEqual("Value1", ht["Key1"], "Wrong object returned!");
Assert.AreEqual("Value2", ht["Key2"], "Wrong object returned!");
}
這將確認(rèn)我可以首先向 Hashtable 中添加值并隨后檢索相應(yīng)的值 — 這是一個(gè)很簡(jiǎn)單的測(cè)試,但能夠表現(xiàn) NUnit 的功能。存在許多測(cè)試類(lèi)型以及各種 Assert 方法,可使用它們來(lái)測(cè)試代碼的每個(gè)部分。
要運(yùn)行該測(cè)試,我需要生成項(xiàng)目,在 NUnit 應(yīng)用程序中打開(kāi)生成的程序集,然后單擊 Run 按鈕。圖 5 顯示了結(jié)果。當(dāng)我看到那個(gè)大的綠色條紋時(shí),我有一種興奮和頭暈的感覺(jué),因?yàn)樗屛抑罍y(cè)試已經(jīng)通過(guò)了。這個(gè)簡(jiǎn)單的示例表明 NUnit 和單元測(cè)試是多么方便和強(qiáng)大。由于能夠編寫(xiě)可以保存的單元測(cè)試,并且每當(dāng)您更改代碼時(shí)都可以重新運(yùn)行該單元測(cè)試,您不僅可以更容易地檢測(cè)到代碼中的缺陷,而且最終能夠交付更好的應(yīng)用程序。
圖 5 NUnit
NUnit 是一個(gè)開(kāi)放源代碼項(xiàng)目,并且可以從 http://www.nunit.org 下載。還有一個(gè)優(yōu)秀的 NUnit Visual Studio .NET 外接程序,它使您可以直接從 Visual Studio 中運(yùn)行單元測(cè)試。您可以在 http://sourceforge.net/projects/nunitaddin 找到它。有關(guān) NUnit 及其在測(cè)試驅(qū)動(dòng)開(kāi)發(fā)中的地位的詳細(xì)信息,請(qǐng)參閱文章“Test-Driven C#: Improve the Design and Flexibility of Your Project with Extreme Programming Techniques”(MSDN ®Magazine 2004 年 4 月刊)。
FxCop
.NET 框架非常強(qiáng)大,這意味著存在創(chuàng)建優(yōu)秀應(yīng)用程序的極大可能,但是也同樣存在創(chuàng)建劣質(zhì)程序的可能。FxCop 是有助于創(chuàng)建更好的應(yīng)用程序的工具之一,它所采用的方法是:使您能夠分析程序集,并使用一些不同的規(guī)則來(lái)檢查它是否符合這些規(guī)則。FxCop 隨附了由 Microsoft 創(chuàng)建的固定數(shù)量的規(guī)則,但您也可以創(chuàng)建并包括您自己的規(guī)則。例如,如果您決定所有的類(lèi)都應(yīng)該具有一個(gè)不帶任何參數(shù)的默認(rèn)構(gòu)造函數(shù),則可以編寫(xiě)一條規(guī)則,以確保程序集的每個(gè)類(lèi)上都具有一個(gè)構(gòu)造函數(shù)。這樣,無(wú)論是誰(shuí)編寫(xiě)該代碼,您都將獲得一定程度的一致性。如果您需要有關(guān)創(chuàng)建自定義規(guī)則的詳細(xì)信息,請(qǐng)參閱 John Robbins 的有關(guān)該主題的 Bugslayer 專(zhuān)欄文章(MSDN ® Magazine 2004 年 6 月刊)。
那么,讓我們觀察一下實(shí)際運(yùn)行的 FxCop,并且看一下它在我一直在處理的 NUnitExample 程序集中找到哪些錯(cuò)誤。當(dāng)您打開(kāi) FxCop 時(shí),您首先需要?jiǎng)?chuàng)建一個(gè) FxCop 項(xiàng)目,然后向其添加您要測(cè)試的程序集。在將該程序集添加到項(xiàng)目以后,就可以按 Analyze,F(xiàn)xCop 將分析該程序集。圖 6 中顯示了在該程序集中找到的錯(cuò)誤和警告。
圖 6
FxCop 在我的程序集中找到了幾個(gè)問(wèn)題。您可以雙擊某個(gè)錯(cuò)誤以查看詳細(xì)信息,包括規(guī)則說(shuō)明以及在哪里可以找到更多信息。(您可以做的一件有趣的事情是在框架程序集上運(yùn)行 FxCop 并查看發(fā)生了什么事情。)
FxCop 可以幫助您創(chuàng)建更好的、更一致的代碼,但它無(wú)法補(bǔ)償?shù)土拥膽?yīng)用程序設(shè)計(jì)或非常簡(jiǎn)單拙劣的編程。FxCop 也不能替代對(duì)等代碼檢查,但是因?yàn)樗梢栽谶M(jìn)行代碼檢查之前捕獲大量錯(cuò)誤,所以您可以花費(fèi)更多時(shí)間來(lái)解決嚴(yán)重的問(wèn)題,而不必?fù)?dān)心命名約定。FxCop 由 Microsoft 開(kāi)發(fā),并且可以從 http://www.gotdotnet.com/team/fxcop 下載。
Lutz Roeder 的 .NET Reflector
下一個(gè)必不可少的工具稱(chēng)為 .NET Reflector,它是一個(gè)類(lèi)瀏覽器和反編譯器,可以分析程序集并向您展示它的所有秘密。.NET 框架向全世界引入了可用來(lái)分析任何基于 .NET 的代碼(無(wú)論它是單個(gè)類(lèi)還是完整的程序集)的反射概念。反射還可以用來(lái)檢索有關(guān)特定程序集中包含的各種類(lèi)、方法和屬性的信息。使用 .NET Reflector,您可以瀏覽程序集的類(lèi)和方法,可以分析由這些類(lèi)和方法生成的 Microsoft 中間語(yǔ)言 (MSIL),并且可以反編譯這些類(lèi)和方法并查看 C# 或 Visual Basic ®.NET 中的等價(jià)類(lèi)和方法。
為了演示 .NET Reflector 的工作方式,我將加載和分析前面已經(jīng)顯示的 NUnitExample 程序集。圖 7 顯示了 .NET Reflector 中加載的該程序集。
圖 7 NUnitExample 程序集
在 .NET Reflector 內(nèi)部,有各種可用來(lái)進(jìn)一步分析該程序集的工具。要查看構(gòu)成某個(gè)方法的 MSIL,請(qǐng)單擊該方法并從菜單中選擇 Disassembler。
除了能夠查看 MSIL 以外,您還可以通過(guò)選擇 Tools 菜單下的 Decompiler 來(lái)查看該方法的 C# 形式。通過(guò)在 Languages 菜單下更改您的選擇,您還可以查看該方法被反編譯到 Visual Basic .NET 或 Delphi 以后的形式。以下為 .NET Reflector 生成的代碼:
public void HashtableAddTest()
{
Hashtable hashtable1;
hashtable1 = new Hashtable();
hashtable1.Add("Key1", "Value1");
hashtable1.Add("Key2", "Value2");
Assert.AreEqual("Value1", hashtable1["Key1"],
"Wrong object returned!");
Assert.AreEqual("Value2", hashtable1["Key2"],
"Wrong object returned!");
}
前面的代碼看起來(lái)非常像我為該方法實(shí)際編寫(xiě)的代碼。以下為該程序集中的實(shí)際代碼:
public void HashtableAddTest()
{
Hashtable ht = new Hashtable();
ht.Add("Key1", "Value1");
ht.Add("Key2", "Value2");
Assert.AreEqual("Value1", ht["Key1"],
"Wrong object returned!");
Assert.AreEqual("Value2", ht["Key2"],
"Wrong object returned!");
}
盡管上述代碼中存在一些小的差異,但它們?cè)诠δ苌鲜峭耆嗤摹?br>
雖然該示例是一種顯示實(shí)際代碼與反編譯代碼之間對(duì)比的好方法,但在我看來(lái),它并不代表 .NET Reflector 所具有的最佳用途 — 分析 .NET 框架程序集和方法。.NET 框架提供了許多執(zhí)行類(lèi)似操作的不同方法。例如,如果您需要從 XML 中讀取一組數(shù)據(jù),則存在多種使用 XmlDocument、XPathNavigator 或 XmlReader 完成該工作的不同方法。通過(guò)使用 .NET Reflector,您可以查看 Microsoft 在編寫(xiě)數(shù)據(jù)集的 ReadXml 方法時(shí)使用了什么,或者查看他們?cè)趶呐渲梦募x取數(shù)據(jù)時(shí)做了哪些工作。.NET Reflector 還是一個(gè)了解以下最佳實(shí)施策略的優(yōu)秀方法:創(chuàng)建諸如 HttpHandlers 或配置處理程序之類(lèi)的對(duì)象,因?yàn)槟梢粤私獾?Microsoft 工作組實(shí)際上是如何在框架中生成這些對(duì)象的。
.NET Reflector 由 Lutz Roeder 編寫(xiě),并且可以從 http://www.aisto.com/roeder/dotnet 下載。
NDoc
編寫(xiě)代碼文檔資料幾乎總是一項(xiàng)令人畏懼的任務(wù)。我所說(shuō)的不是早期設(shè)計(jì)文檔,甚至也不是更為詳細(xì)的設(shè)計(jì)文檔;我說(shuō)的是記錄類(lèi)上的各個(gè)方法和屬性。NDoc 工具能夠使用反射來(lái)分析程序集,并使用從 C# XML 注釋生成的 XML 自動(dòng)為代碼生成文檔資料。XML 注釋僅適用于 C#,但有一個(gè)名為 VBCommenter 的 Visual Studio .NET Power Toy,它能夠?yàn)?Visual Basic .NET 完成類(lèi)似的工作。此外,下一版本的 Visual Studio 將為更多語(yǔ)言支持 XML 注釋。
使用 NDoc 時(shí),您仍然在編寫(xiě)代碼的技術(shù)文檔,但您是在編寫(xiě)代碼的過(guò)程中完成了文檔編寫(xiě)工作(在 XML 注釋中),而這更容易忍受。使用 NDoc 時(shí),第一步是為您的程序集打開(kāi) XML 注釋生成功能。右鍵單擊該項(xiàng)目并選擇 Properties Configuration Properties Build,然后在 XML Documentation File 選項(xiàng)中輸入用于保存 XML 文件的路徑。當(dāng)該項(xiàng)目生成時(shí),將創(chuàng)建一個(gè) XML 文件,其中包含所有 XML 注釋。下面是 NUnit 示例中的一個(gè)用 XML 編寫(xiě)了文檔的方法:
/// <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
}
有關(guān)該方法的 XML 文檔資料將被提取并保存在 XML 文件中,如下所示:
<member name="M:NUnitExample.HashtableTest.HashtableAddTest">
<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 使用反射來(lái)考察您的程序集,然后讀取該文檔中的 XML,并且將它們進(jìn)行匹配。NDoc 使用該數(shù)據(jù)來(lái)創(chuàng)建任意數(shù)量的不同文檔格式,包括 HTML 幫助文件 (CHM)。在生成 XML 文件以后,下一步是將程序集和 XML 文件加載到 NDoc 中,以便可以對(duì)它們進(jìn)行處理。通過(guò)打開(kāi) NDoc 并單擊 Add 按鈕,可以容易地完成該工作。
在將程序集和 XML 文件加載到 NDoc 中并且使用可用的屬性范圍自定義輸出以后,單擊 Generate 按鈕將啟動(dòng)生成文檔資料的過(guò)程。使用默認(rèn)的屬性,NDoc 可以生成一些非常吸引人并且實(shí)用的 .html 和 .chm 文件,從而以快速有效的方式自動(dòng)完成原來(lái)非常乏味的任務(wù)。
NDoc 是一個(gè)開(kāi)放源代碼項(xiàng)目,并且可以從 http://ndoc.sourceforge.net 下載。
NAnt
NAnt 是一個(gè)基于 .NET 的生成工具,與當(dāng)前版本的 Visual Studio .NET 不同,它使得為您的項(xiàng)目創(chuàng)建生成過(guò)程變得非常容易。當(dāng)您擁有大量從事單個(gè)項(xiàng)目的開(kāi)發(fā)人員時(shí),您不能依賴(lài)于從單個(gè)用戶(hù)的座位進(jìn)行生成。您也不希望必須定期手動(dòng)生成該項(xiàng)目。您更愿意創(chuàng)建每天晚上運(yùn)行的自動(dòng)生成過(guò)程。NAnt 使您可以生成解決方案、復(fù)制文件、運(yùn)行 NUnit 測(cè)試、發(fā)送電子郵件,等等。遺憾的是,NAnt 缺少漂亮的圖形界面,但它的確具有可以指定應(yīng)該在生成過(guò)程中完成哪些任務(wù)的控制臺(tái)應(yīng)用程序和 XML 文件。注意,MSBuild(屬于 Visual Studio 2005 的新的生成平臺(tái))為每種健壯的生成方案進(jìn)行了準(zhǔn)備,并且由基于 XML 的項(xiàng)目文件以類(lèi)似的方式驅(qū)動(dòng)。
實(shí)際運(yùn)行的 NAnt
在該示例中,我將為前面創(chuàng)建的 NUnitExample 解決方案創(chuàng)建一個(gè) NAnt 版本文件。首先,我需要?jiǎng)?chuàng)建一個(gè)具有 .build 擴(kuò)展名的 XML 文件,將其放在我的項(xiàng)目的根目錄中,然后向該文件的頂部添加一個(gè) XML 聲明。我需要添加到該文件的第一個(gè)標(biāo)記是 project 標(biāo)記:
<?xml version="1.0"?>
<project name="NUnit Example" default="build" basedir=".">
<description>The NUnit Example Project</description>
</project>
項(xiàng)目標(biāo)記還用于設(shè)置項(xiàng)目名稱(chēng)、默認(rèn)目標(biāo)以及基目錄。Description 標(biāo)記用于設(shè)置該項(xiàng)目的簡(jiǎn)短說(shuō)明。
接下來(lái),我將添加 property 標(biāo)記,該標(biāo)記可用于將設(shè)置存儲(chǔ)到單個(gè)位置(隨后可以從文件中的任意位置訪問(wèn)該位置)。在該例中,我將創(chuàng)建一個(gè)名為 debug 的屬性,我可以隨后將其設(shè)置為 true 或 false,以反映我是否要在調(diào)試配置下編譯該項(xiàng)目。(最后,這一特定屬性并未真正影響如何生成該項(xiàng)目;它只是您設(shè)置的一個(gè)變量,當(dāng)您真正確定了如何生成該項(xiàng)目時(shí)將讀取該變量。)
接下來(lái),我需要?jiǎng)?chuàng)建一個(gè) target 標(biāo)記。一個(gè)項(xiàng)目可以包含多個(gè)可在 NAnt 運(yùn)行時(shí)指定的 target。如果未指定 target,則使用默認(rèn) target(我在 project 元素中設(shè)置的 target)。在該示例中,默認(rèn) target 是 build。讓我們觀察一下 target 元素,它將包含大多數(shù)生成信息:
<target name="build" description="compiles the source code">
</target>
在 target 元素內(nèi),我將把 target 的名稱(chēng)設(shè)置為 build,并且創(chuàng)建有關(guān)該 target 將做哪些工作的說(shuō)明。我還將創(chuàng)建一個(gè) csc 元素,該元素用于指定應(yīng)該傳遞給 csc C# 編譯器的數(shù)據(jù)。讓我們看一下該 csc 元素:
<csc target="library" output=".\bin\debug\NUnitExample.dll"
debug="${debug}">
<references>
<includes name="C:\program files\NUnit V2.1\bin\NUnit.Framework.dll"/>
</references>
<sources>
<includes name="HashtableTest.cs"/>
</sources>
</csc>
首先,我必須設(shè)置該 csc 元素的 target。在該例中,我將創(chuàng)建一個(gè) .dll 文件,因此我將 target 設(shè)置為 library。接下來(lái),我必須設(shè)置 csc 元素的 output,它是將要?jiǎng)?chuàng)建 .dll 文件的位置。最后,我需要設(shè)置 debug 屬性,它確定了是否在調(diào)試中編譯該項(xiàng)目。因?yàn)槲以谇懊鎰?chuàng)建了一個(gè)用于存儲(chǔ)該值的屬性,所以我可以使用下面的字符串來(lái)訪問(wèn)該屬性的值:${debug}。Csc 元素還包含一些子元素。我需要?jiǎng)?chuàng)建兩個(gè)元素:references 元素將告訴 NAnt 需要為該項(xiàng)目引用哪些程序集,sources 元素告訴 NAnt 要在生成過(guò)程中包含哪些文件。在該示例中,我引用了 NUnit.Framework.dll 程序集并包含了 HashtableTest.cs 文件。以下代碼中顯示了完整的生成文件。(您通常還要?jiǎng)?chuàng)建一個(gè)干凈的 target,用于刪除生成的文件,但為了簡(jiǎn)潔起見(jiàn),我已經(jīng)將其省略。)
<?xml version="1.0"?>
<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\NUnitExample.dll"
debug="${debug}">
<references>
<includes name="C:\program files\NUnit
V2.1\bin\NUnit.Framework.dll" />
</references>
<sources>
<includes name="HashtableTest.cs"/>
</sources>
</csc>
</target>
</project>
要生成該文件,我需要轉(zhuǎn)到我的項(xiàng)目的根目錄(生成文件位于此處),然后從該位置執(zhí)行 nant.exe。如果生成成功,您可以在該應(yīng)用程序的 bin 目錄中找到 .dll 和 .pdb 文件。盡管使用 NAnt 肯定不像在 Visual Studio 中單擊 Build 那樣簡(jiǎn)單,但它仍然是一種非常強(qiáng)大的工具,可用于開(kāi)發(fā)按自動(dòng)計(jì)劃運(yùn)行的生成過(guò)程。NAnt 還包括一些有用的功能,例如能夠運(yùn)行單元測(cè)試或者復(fù)制附加文件(這些功能沒(méi)有受到當(dāng)前 Visual Studio 生成過(guò)程的支持)。
NAnt 是一個(gè)開(kāi)放源代碼項(xiàng)目,并且可以從 http://nant.sourceforge.net 下載。
轉(zhuǎn)換工具
我已經(jīng)將兩個(gè)獨(dú)立的工具合在一起放在標(biāo)題“轉(zhuǎn)換工具”下面。這兩個(gè)工具都非常簡(jiǎn)單,但又可能極為有用。第一個(gè)工具是 ASP.NET 版本轉(zhuǎn)換器,它可用于轉(zhuǎn)換 ASP.NET(虛擬目錄在它下面運(yùn)行)的版本。第二個(gè)工具是 Visual Studio Converter,它可用于將項(xiàng)目文件從 Visual Studio .NET 2002 轉(zhuǎn)換到 Visual Studio .NET 2003。
當(dāng) IIS 處理請(qǐng)求時(shí),它會(huì)查看正在請(qǐng)求的文件的擴(kuò)展名,然后基于該 Web 站點(diǎn)或虛擬目錄的擴(kuò)展名映射,將請(qǐng)求委派給 ISAPI 擴(kuò)展或者自己處理該請(qǐng)求。這正是 ASP.NET 的工作方式;將為所有 ASP.NET 擴(kuò)展名注冊(cè)擴(kuò)展名映射,并將這些擴(kuò)展名映射導(dǎo)向 aspnet_isapi.dll。這種工作方式是完美無(wú)缺的,除非您安裝了 ASP.NET 1.1 — 它會(huì)將擴(kuò)展名映射升級(jí)到新版本的 aspnet_isapi.dll。當(dāng)在 ASP.NET 1.0 上生成的應(yīng)用程序試圖用 1.1 版運(yùn)行時(shí),這會(huì)導(dǎo)致錯(cuò)誤。要解決該問(wèn)題,可以將所有擴(kuò)展名映射重新轉(zhuǎn)換到 1.0 版的 aspnet_isapi.dll,但是由于有 18 種擴(kuò)展名映射,所以手動(dòng)完成這一工作將很枯燥。這正是 ASP.NET 版本轉(zhuǎn)換器可以發(fā)揮作用的時(shí)候。使用這一小型實(shí)用工具,可以轉(zhuǎn)換任何單個(gè) ASP.NET 應(yīng)用程序所使用的 .NET 框架的版本。
圖 9 ASP.NET 版本轉(zhuǎn)換器
圖 9 顯示了實(shí)際運(yùn)行的 ASP.NET 版本轉(zhuǎn)換器。它的使用方法非常簡(jiǎn)單,只須選擇相應(yīng)的應(yīng)用程序,然后選擇您希望該應(yīng)用程序使用的 .NET 框架版本。該工具隨后將使用 aspnet_regiis.exe 命令行工具將該應(yīng)用程序轉(zhuǎn)換到所選版本的框架。隨著將來(lái)版本的 ASP.NET 和 .NET 框架的發(fā)布,該工具將變得更為有用。
ASP.NET 版本轉(zhuǎn)換器由 Denis Bauer 編寫(xiě),并且可以從 http://www.denisbauer.com/NETTools/ASPNETVersionSwitcher.aspx 下載。
Visual Studio .NET 項(xiàng)目轉(zhuǎn)換器(參見(jiàn)圖 10)非常類(lèi)似于 ASP.NET 版本轉(zhuǎn)換器,區(qū)別在于它用于轉(zhuǎn)換 Visual Studio 項(xiàng)目文件的版本。盡管在 .NET 框架的 1.0 版和 1.1 版之間只有很小的差異,但一旦將項(xiàng)目文件從 Visual Studio .NET 2002 轉(zhuǎn)換到 Visual Studio .NET 2003,將無(wú)法再把它轉(zhuǎn)換回去。雖然這在大多數(shù)時(shí)候可能不會(huì)成為問(wèn)題(因?yàn)樵?.NET 框架 1.0 版和 1.1 版之間幾乎沒(méi)有什么破壞性的更改),但在某些時(shí)刻您可能需要將項(xiàng)目轉(zhuǎn)換回去。該轉(zhuǎn)換器可以將任何解決方案或項(xiàng)目文件從 Visual Studio 7.1 (Visual Studio .NET 2003) 轉(zhuǎn)換到 Visual Studio 7.0 (Visual Studio .NET 2002),并在必要時(shí)進(jìn)行反向轉(zhuǎn)換。
圖 10 Visual Studio .NET 項(xiàng)目轉(zhuǎn)換器
Visual Studio .NET 項(xiàng)目轉(zhuǎn)換器由 Dacris Software 編寫(xiě)。該工具可以從 http://www.codeproject.com/macro/vsconvert.asp 下載。
小結(jié)
本文采用走馬觀花的方式介紹了上述工具,但我已經(jīng)試圖起碼向您提供足夠的信息以激起您的好奇心。我相信本文已經(jīng)讓您在某種程度上領(lǐng)悟了幾個(gè)免費(fèi)工具,您可以立即開(kāi)始使用這些工具來(lái)編寫(xiě)更好的項(xiàng)目。同時(shí),我還要敦促您確保自己擁有所有其他可以獲得的合適工具,無(wú)論是最新版本的 Visual Studio、功能強(qiáng)大的計(jì)算機(jī)還是免費(fèi)的實(shí)用工具。擁有合適的工具將使一切變得