共用方式為


使用 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 文字範本的方針