共用方式為


使用 T4 文字範本在設計階段產生程式碼

設計階段 T4 文字範本可讓您在 Visual Studio 專案中產生程式碼和其他檔案。通常您會撰寫範本,讓範本可以改變依據「模型」(Model) 的資料而產生的程式碼。模式是一種檔案或資料庫,其中包含應用程式需求的重要資訊。

例如,您可能擁有將工作流程定義為資料表或圖表的模型。從這個模型,即可產生執行該工作流程的軟體。當使用者的需求改變時,可輕鬆與使用者討論新的工作流程。從工作流程重新產生程式碼比手動更新程式碼更為可靠。

注意事項注意事項

「模型」(Model) 是描述應用程式特定層面的資料來源。它可以是以任何檔案或資料庫類型為形式的任何格式。不一定非得是特定格式,例如 UML 模型或網域指定的語言模型。模型的格式一般為資料表或 XML 檔案。

您可能已經熟悉程式碼產生作業。當您在 Visual Studio 方案的 .resx 檔中定義資源時,將會自動產生一組類別和方法。資源檔讓編輯資源的工作變得比編輯類別和方法更輕鬆也更可靠。有了文字範本,您就可以用相同的方式從自己設計的原始檔產生程式碼。

文字範本中混合了要產生的文字和會產生文字可變部分的程式碼。程式碼可讓您重複或依條件省略產生之文字的組成部分。產生的文字本身可以是會構成應用程式之一部分的程式碼。

建立設計階段 T4 文字範本

若要在 Visual Studio 中建立設計階段 T4 範本

  1. 建立 Visual Studio 專案或開啟現有專案。

    例如,在 [檔案] 功能表上,選擇 [新增], [Project]。

  2. 加入文字範本檔加入至專案並將其副檔名為 .tt 的名稱。

    若要這麼做,請在 [方案總管],在專案的捷徑功能表,選擇[新增], [新項目]。在 [新增項目] 對話方塊中選擇 [文字範本] 從中間窗格。

    請注意,該檔案的 [自訂工具] 屬性是 [TextTemplatingFileGenerator]。

  3. 開啟檔案。其中已經包含下列指示詞:

    <#@ template hostspecific="false" language="C#" #>
    <#@ output extension=".txt" #>
    

    如果您已將範本加入至 Visual Basic 專案,則語言屬性將會是 "VB"。

  4. 在檔案結尾加入一些文字。例如:

    Hello, world!
    
  5. 儲存檔案。

    您可能會看到 [安全性警告] 訊息方塊,要求確認是否要執行範本。按一下 [確定]。

  6. 在 [方案總管],展開範本檔案節點,您會發現有 .txt 副檔名的檔案。檔案包含從範本產生的文字。

    注意事項注意事項

    如果您的專案是 Visual Basic 專案中,您必須按一下 [顯示所有檔案] 才能看見輸出檔。

Dd820620.collapse_all(zh-tw,VS.110).gif重新產生程式碼

在下列任一情況中,將會執行範本並產生附屬檔案:

  • 編輯樣板接著將焦點變更至不同的 Visual Studio 視窗。

  • 儲存範本。

  • 在 [組建] 功能表的[轉換所有範本] 。如此隨即轉換 Visual Studio 方案中的所有範本。

  • 在 [方案總管],在所有檔案捷徑功能表,選取 [執行自訂工具]。使用這個方法會將範本的替代的子集。

您也可以設定 Visual Studio 專案,以便在範本所讀取的檔案變更時執行範本。如需詳細資訊,請參閱自動重新產生程式碼。

產生變數文字

文字範本可讓您使用程式碼來變更產生之程式碼的內容。

若要使用程式碼來產生文字

  1. 變更 .tt 檔案的內容:

    <#@ template 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 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
    #>
    
  2. 儲存 .tt 檔,並再次檢查產生的 .txt 檔。它會列出數字 0 到 9 的平方值。

請注意,陳述式是置於 <#...#> 內,而單一運算式則是置於 <#=...#> 內。如需詳細資訊,請參閱撰寫 T4 文字範本

如果要在 Visual Basic 撰寫生成程式碼 (Generating Code),template 指示詞必須包含 language="VB"。"C#" 為預設值。

偵錯設計階段 T4 文字範本

偵錯文字範本:

  • 將 debug="true" 插入 template 指示詞。例如:

    <#@ template debug="true" hostspecific="false" language="C#" #>

  • 將範本,方式與您為一般程式碼會的中斷點。

  • 從文字範本檔的捷徑功能表在方案總管中選取 [偵錯 T4 範本] 。

範本會執行並在中斷點停止。您可以透過程式碼檢查變數和步驟以一般方式。

提示提示

debug="true" 更精確地產生的程式碼對應至文字範本,透過插入詳細行號指示詞到產生的程式碼。如果您忽略它,中斷點可能會停止在錯誤狀態中執行。

即使您沒有進行偵錯,不過,您可以在範本指示詞中的子句)。這會導致效能的只非常小置放。

產生方案的程式碼或資源

您可以根據模型產生不同的程式檔案。模型是像資料庫、組態檔、UML 模型、DSL 模型或其他來源之類的輸入。您通常可以從相同的模型產生許多程式檔。為了達到這個目的,您要為每個產生的程式檔建立範本檔,並讓所有的範本都讀取相同的模型。

若要產生程式碼或資源

  1. 變更輸出指示詞以產生適當類型的檔案,例如 .cs、.vb、.resx 或 .xml 檔。

  2. 插入將會產生所需方案程式碼的程式碼。例如,如果您要在類別中產生三個整數欄位宣告,就插入下列程式碼:

                      <#@ 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
    #>
    }
    
  3. 儲存檔案並檢查產生的檔案,這個檔案現在包含了下列程式碼:

    class MyGeneratedClass {
      private int P1 = 0; 
      private int P2 = 0;
      private int P3 = 0;
    }
    

Dd820620.collapse_all(zh-tw,VS.110).gif生成程式碼和產生的文字

產生程式碼時,最重要的是要避免讓在範本中執行之生成程式碼 (Generating Code) 與結果成為方案之一部分的產生程式碼 (Generated Code) 混淆不清。這兩個程式碼的語言不一定要相同。

上一個範例有兩個版本。在其中一個版本中,產生的程式碼語言為 C#。在另一個版本中,產生的程式碼語言為 Visual Basic。但是這兩者產生的文字相同,屬於 C# 類別。

您可以用相同的方式,使用 Visual C# 範本來產生以任何語言撰寫的程式碼。產生的文字不一定非得是特定語言,也不一定非得是程式的程式碼。

Dd820620.collapse_all(zh-tw,VS.110).gif建構文字範本

依照良好的慣例,我們傾向於將範本程式碼分隔成兩部分:

  • 組態或資料收集部分,會在變數中設定值,但不包含文字區塊。在上一個範例中,這部分是 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")
#>

Dd820620.collapse_all(zh-tw,VS.110).gif使用相對路徑名稱開啟檔案

若要從文字範本的相對位置載入檔案,請使用 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。

Dd820620.collapse_all(zh-tw,VS.110).gif從 Visual Studio 取得資料

若要使用提供的服務。 Visual Studio,請將 hostSpecific 屬性並載入 EnvDTE 組件。您可以使用 IServiceProvider.GetCOMService() 存取 DTE 和其他服務。例如:

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ assembly name="EnvDTE" #>
<#
  IServiceProvider serviceProvider = (IServiceProvider)this.Host;
  EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetCOMService(typeof(EnvDTE.DTE));
#>

Number of projects in this VS solution:  <#= dte.Solution.Projects.Count #>
提示提示

文字範本會在其應用程式網域中執行,因此,這項服務會透過封送處理存取。在這種情況下, GetCOMService() 比 GetService() 可靠。

自動重新產生程式碼

一般而言,會使用一個輸入模型產生 Visual Studio 方案中的數個檔案。每個檔案各自從本身的範本產生,但這些範本都參考同一個模型。

如果來源模型變更,就必須重新執行方案中的所有範本。若要手動執行這項操作,請選取在 [組建] 功能表的 [轉換所有範本] 。

如果您已安裝 Visual Studio Visualization and Modeling SDK,即可在每次建置時自動轉換所有範本。若要這麼做,請以文字編輯器來編輯專案檔 (.csproj 或 .vbproj),並在檔案結尾附近的所有其他 <import> 陳述式之後加入下列幾行:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.0\TextTemplating\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# 檔案),然後逐步加入變更結果檔案的產生程式碼。

若要將現有檔案轉換設計階段範本

  1. 在 Visual Studio 專案中,加入要產生的檔案類型,例如 .cs、.vb 或 .resx 檔案。

  2. 測試新檔案以確定可以運作。

  3. 在 [方案總管] 中,將副檔名變更為 .tt

  4. 確認 .tt 檔案的下列屬性:

    自訂工具 =

    TextTemplatingFileGenerator

    建置動作 =

    None

  5. 在檔案開頭插入下列幾行:

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ output extension=".cs" #>
    

    如果您想要以 Visual Basic 撰寫範本的生成程式碼,請將 language 屬性設為 "VB" 而非 "C#"。

    將 extension 屬性設定為要產生之檔案類型的副檔名,例如 .cs、.resx 或 .xml。

  6. 儲存檔案。

    具有指定之副檔名的附屬檔案隨即建立。就檔案類型來看,其屬性是正確的。例如,.cs 檔案的 [建置動作] 屬性將會是 [編譯]。

    確認產生的檔案與原來的檔案包含相同內容。

  7. 找出您想要在檔案中變更的部分。例如,僅在特定情況下出現的部分,或重複的部分,或是其特定值有所不同的部分。插入生成程式碼。儲存檔案,並確認已正確產生附屬檔案。重複此步驟。

程式碼產生作業的方針

請參閱撰寫 T4 文字範本的方針

後續步驟

後續步驟

主題

透過使用輔助功能 (包括檔案和持續性資料) 的程式碼,撰寫和偵錯更進階的文字範本。

撰寫 T4 文字範本

在執行階段從範本產生文件。

使用 T4 文字範本在執行階段產生文字

在 Visual Studio 外部執行文字產生作業。

使用 TextTransform 公用程式產生檔案

將資料的形式轉換為 Domain-Specific Language。

從網域指定的語言產生程式碼

撰寫指示詞處理器來轉換自己的資料來源。

自訂 T4 文字轉換

請參閱

概念

撰寫 T4 文字範本的方針