使用 T4 文字範本在設計階段產生程式碼
更新:2010 年 10 月
設計階段 T4 文字範本可讓您在 Visual Studio 專案中產生程式碼和其他檔案。 通常您會撰寫範本,讓範本可以改變依據「模型」(Model) 的資料而產生的程式碼。 模式是一種檔案或資料庫,其中包含應用程式需求的重要資訊。
例如,您可能擁有將工作流程定義為資料表或圖表的模型。 從這個模型,即可產生執行該工作流程的軟體。 當使用者的需求改變時,可輕鬆與使用者討論新的工作流程。 從工作流程重新產生程式碼比手動更新程式碼更為可靠。
![]() |
---|
「模型」(Model) 是描述應用程式特定層面的資料來源。 它可以是以任何檔案或資料庫類型為形式的任何格式。 不一定非得是特定格式,例如 UML 模型或網域指定的語言模型。 模型的格式一般為資料表或 XML 檔案。 |
您可能已經熟悉程式碼產生作業。 當您在 Visual Studio 方案的 .resx 檔中定義資源時,將會自動產生一組類別和方法。 資源檔讓編輯資源的工作變得比編輯類別和方法更輕鬆也更可靠。 有了文字範本,您就可以用相同的方式從自己設計的原始檔產生程式碼。
文字範本中混合了要產生的文字和會產生文字可變部分的程式碼。 程式碼可讓您重複或依條件省略產生之文字的組成部分。 產生的文字本身可以是會構成應用程式之一部分的程式碼。
建立設計階段 T4 文字範本
若要在 Visual Studio 中建立設計階段 T4 範本
建立 Visual Studio 專案或開啟現有專案。
例如,在 [檔案] 功能表上,指向 [新增],然後按一下 [專案]。
將文字範本檔加入至專案,並命名為 NewTemplate.tt。
若要這樣做,請在 [方案總管] 中以滑鼠右鍵按一下您的專案,然後指向 [加入],再按一下 [新增項目]。 在 [加入新項目] 對話方塊的 [範本] 窗格中選取 [文字範本]。 將檔案命名為 NewTemplate.tt。
請注意,該檔案的 [自訂工具] 屬性是 [TextTemplatingFileGenerator]。
開啟檔案。 其中已經包含下列指示詞:
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".txt" #>
如果您已將範本加入至 Visual Basic 專案,則語言屬性將會是 "VB"。
在檔案結尾加入一些文字。 例如:
Hello, world!
儲存檔案。
您可能會看到 [安全性警告] 訊息方塊,要求確認是否要執行範本。 按一下 [確定]。
在 [方案總管] 中,展開 NewTemplate.tt 節點,您將會發現名為 NewTemplate.txt 的檔案。 該檔案會包含您所輸入的文字。
注意事項
如果是 Visual Basic 專案,您必須按一下 [顯示所有檔案] 才能看到 NewTemplate.txt 輸出檔。
重新產生程式碼
在下列任一情況中,將會執行範本並產生附屬檔案:
編輯範本,然後將焦點變更為其他 Visual Studio 視窗。
儲存範本。
按一下 [方案總管] 工具列中的 [轉換所有範本]。 如此隨即轉換 Visual Studio 方案中的所有範本。
在 [方案總管] 中,以滑鼠右鍵按一下一個或多檔案,然後按一下 [執行自訂工具]。 使用這個方法即可轉換一組已選取的範本。
您也可以設定 Visual Studio 專案,以便在範本所讀取的檔案變更時執行範本。 如需詳細資訊,請參閱自動重新產生程式碼。
產生變數文字
文字範本可讓您使用程式碼來變更產生之程式碼的內容。
若要使用程式碼來產生文字
變更 .tt 檔案的內容:
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".txt" #> <#int top = 10; for (int i = 0; i<=top; i++) { #> The square of <#= i #> is <#= i*i #> <# } #>
<#@ template debug="false" hostspecific="false" language="VB" #> <#@ output extension=".txt" #> <#Dim top As Integer = 10 For i As Integer = 0 To top #> The square of <#= i #> is <#= i*i #> <# Next #>
儲存 .tt 檔,並再次檢查產生的 .txt 檔。 它會列出數字 0 到 9 的平方值。
請注意,陳述式是置於 <#...#> 內,而單一運算式則是置於 <#=...#> 內。 如需詳細資訊,請參閱撰寫 T4 文字範本。
如果要在 Visual Basic 撰寫生成程式碼 (Generating Code),template 指示詞必須包含 language="VB"。 "C#" 為預設值。
產生方案的程式碼或資源
您可以根據模型產生不同的程式檔案。 模型是像資料庫、組態檔、UML 模型、DSL 模型或其他來源之類的輸入。 您通常可以從相同的模型產生許多程式檔。 為了達到這個目的,您要為每個產生的程式檔建立範本檔,並讓所有的範本都讀取相同的模型。
若要產生程式碼或資源
變更輸出指示詞以產生適當類型的檔案,例如 .cs、.vb、.resx 或 .xml 檔。
插入將會產生所需方案程式碼的程式碼。 例如,如果您要在類別中產生三個整數欄位宣告,就插入下列程式碼:
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".cs" #> <# var properties = new string [] {"P1", "P2", "P3"}; #> class MyGeneratedClass { <# foreach (string propertyName in properties) { #> private int <#= propertyName #> = 0; <# } #> }
<#@ template debug="false" hostspecific="false" language="VB" #> <#@ output extension=".cs" #> <# Dim properties = {"P1", "P2", "P3"} #> class MyGeneratedClass { <# For Each propertyName As String In properties #> private int <#= propertyName #> = 0; <# Next #> }
儲存檔案並檢查產生的檔案,這個檔案現在包含了下列程式碼:
class MyGeneratedClass { private int P1 = 0; private int P2 = 0; private int P3 = 0; }
生成程式碼和產生的文字
產生程式碼時,最重要的是要避免讓在範本中執行之生成程式碼 (Generating Code) 與結果成為方案之一部分的產生程式碼 (Generated Code) 混淆不清。 這兩個程式碼的語言不一定要相同。
上一個範例有兩個版本。 在其中一個版本中,產生的程式碼語言為 C#。 在另一個版本中,產生的程式碼語言為 Visual Basic。 但是這兩者產生的文字相同,屬於 C# 類別。
您可以用相同的方式,使用 Visual C# 範本來產生以任何語言撰寫的程式碼。 產生的文字不一定非得是特定語言,也不一定非得是程式的程式碼。
建構文字範本
依照良好的慣例,我們傾向於將範本程式碼分隔成兩部分:
組態或資料收集部分,會在變數中設定值,但不包含文字區塊。 在上一個範例中,這部分是 properties 的初始設定。
有時候這稱為 [模型] 區段,因為它會建構一個存放區內的模式,而且通常會讀取模型檔案。
文字產生部分 (在範例中為 foreach(...){...}),會使用變數的值。
這部分不是必要的分隔,但是為一種風格 -- 透過降低文字部分的複雜度,提高範本的可讀性。
讀取檔案或其他原始檔
若要存取模型檔或資料庫,範本程式碼可以使用 System.XML 這類組件。 若要存取這些組件,則必須插入如下所示的指示詞:
<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.IO" #>
assembly 指示詞可讓指定的組件能夠使用範本程式碼,其方式就如同 Visual Studio 專案中的 [參考] 區段。 您不必包含 System.dll 的參考,這個組件會被自動參考。 import 指示詞讓您不必使用完整名稱就可以使用型別,其使用方式如同一般程式檔中的 using 指示詞。
例如,匯入 System.IO 之後,您可以撰寫:
<# var properties = File.ReadLines("C:\\propertyList.txt");#>
...
<# foreach (string propertyName in properties) { #>
...
<# For Each propertyName As String In
File.ReadLines("C:\\propertyList.txt")
#>
使用相對路徑名稱開啟檔案
若要從文字範本的相對位置載入檔案,請使用 this.Host.ResolvePath()。 若要使用 this.Host,您必須在 template 中設定 hostspecific="true":
<#@ template debug="false" hostspecific="true" language="C#" #>
然後您可以撰寫如下範例內容:
<# string fileName = this.Host.ResolvePath("filename.txt");
string [] properties = File.ReadLines(filename);
#>
...
<# foreach (string propertyName in properties { #>
...
<# Dim fileName = Me.Host.ResolvePath("propertyList.txt")
Dim properties = File.ReadLines(filename)
#>
...
<# For Each propertyName As String In properties
...
#>
您也可以使用 this.Host.TemplateFile,它會識別目前範本檔的名稱。
this.Host (在 VB 中為 Me.Host) 的型別為 Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost。
從 Visual Studio 取得資料
若要使用 Visual Studio 中提供的服務,請設定 hostSpecific 屬性並載入 EnvDTE 組件。 例如:
<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ assembly name="EnvDTE" #>
<#
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetService(typeof(EnvDTE.DTE));
#>
Number of projects in this VS solution: <#= dte.Solution.Projects.Count #>
自動重新產生程式碼
一般而言,會使用一個輸入模型產生 Visual Studio 方案中的數個檔案。 每個檔案各自從本身的範本產生,但這些範本都參考同一個模型。
如果來源模型變更,就必須重新執行方案中的所有範本。 若要手動執行這項工作,請按一下 [方案總管] 工具列中的 [轉換所有範本]。
如果您已安裝 Visual Studio Visualization and Modeling SDK,即可在每次建置時自動轉換所有範本。 若要這麼做,請以文字編輯器來編輯專案檔 (.csproj 或 .vbproj),並在檔案結尾附近的所有其他 <import> 陳述式之後加入下列幾行:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" />
<PropertyGroup>
<TransformOnBuild>true</TransformOnBuild>
<!-- Other properties can be inserted here -->
</PropertyGroup>
如需詳細資訊,請參閱建置流程中的程式碼產生。
錯誤報告
若要在 Visual Studio 錯誤視窗中放置錯誤和警告訊息,您可以使用下列方法:
Error("An error message");
Warning("A warning message");
將現有檔案轉換為範本
範本有個好用的功能,就是加上一些插入的程式碼之後,範本看起來會和它所產生的檔案非常相像。 這讓人想到建立範本的有用方法, 即首先建立一般檔案做為原型 (例如 Visual C# 檔案),然後逐步加入變更結果檔案的產生程式碼。
若要將現有檔案轉換設計階段範本
在 Visual Studio 專案中,加入要產生的檔案類型,例如 .cs、.vb 或 .resx 檔案。
測試新檔案以確定可以運作。
在 [方案總管] 中,將副檔名變更為 .tt。
確認 .tt 檔案的下列屬性:
自訂工具 =
TextTemplatingFileGenerator
建置動作 =
無
在檔案開頭插入下列幾行:
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".cs" #>
如果您想要以 Visual Basic 撰寫範本的生成程式碼,請將 language 屬性設為 "VB" 而非 "C#"。
將 extension 屬性設定為要產生之檔案類型的副檔名,例如 .cs、.resx 或 .xml。
儲存檔案。
具有指定之副檔名的附屬檔案隨即建立。 就檔案類型來看,其屬性是正確的。 例如,.cs 檔案的 [建置動作] 屬性將會是 [編譯]。
確認產生的檔案與原來的檔案包含相同內容。
找出您想要在檔案中變更的部分。 例如,僅在特定情況下出現的部分,或重複的部分,或是其特定值有所不同的部分。 插入生成程式碼。 儲存檔案,並確認已正確產生附屬檔案。 重複此步驟。
程式碼產生作業的方針
請參閱撰寫 T4 文字範本的方針。
後續步驟
後續步驟 |
主題 |
---|---|
透過使用輔助功能 (包括檔案和持續性資料) 的程式碼,撰寫和偵錯更進階的文字範本。 |
|
在執行階段從範本產生文件。 |
|
在 Visual Studio 外部執行文字產生作業。 |
|
將資料的形式轉換為 Domain-Specific Language。 |
|
撰寫指示詞處理器來轉換自己的資料來源。 |
請參閱
其他資源
變更記錄
日期 |
記錄 |
原因 |
---|---|---|
2010 年 10 月 |
加入 VB 範例。 將方針移至不同主題。 |
資訊加強。 |