熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

.Net開發人員應該下載的十種必備工具

2013-11-13 09:59:32  來源: .NET編程 

  ·用於編寫單元測試的 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 編寫該工具可以從 下載


From:http://tw.wingwit.com/Article/program/net/201311/12217.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.