黃聰:VS2010開發T4模版引擎之基礎入門

原文:http://www.cnblogs.com/lzrabbit/archive/2012/07/15/2591085.htmlhtml

  額,T4好陌生的名字,和NuGet同樣很悲催,不爲世人所熟知,卻又在背後默默無聞的奉獻着,直到如今咱們項目組的人除了我以外,其它人仍是對其豪無興趣,基本上是連看一眼都懶得看,可憐的娃啊。。。web

  T4(Text Template Transformation Toolkit)是微軟官方在VisualStudio 2008中開始使用的代碼生成引擎。在 Visual Studio 中,「T4 文本模板」是由一些文本塊和控制邏輯組成的混合模板,它能夠生成文本文件。 在 Visual C# 或 Visual Basic 中,控制邏輯編寫爲程序代碼的片斷。生成的文件能夠是任何類型的文本,例如網頁、資源文件或任何語言的程序源代碼。如今的VS中只要與代碼生成相關的場景基本上都能找T4的身影,好比MVC的視圖模板,Entity Framwork的DataContext模板等等。數據庫

  在學習枯燥的概念前咱們先來看一下用T4模版快速生成POCO實體類的示例
打開VS2010建一個項目,而後右擊項目文件選擇新建項,在文件列表中找到文件模版,如圖所示函數

修改TextTemplate1.tt文件內容以下工具

複製代碼
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{    
    public class User
    {
        /// <summary>
        /// 用戶ID
        /// </summary>
        public int UserID { get; set; }

        /// <summary>
        /// 用戶名
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 密碼
        /// </summary>
        public string Password { get; set; }

        /// <summary>
        /// Email
        /// </summary>
        public string Email { get; set; }

        /// <summary>
        /// 手機號
        /// </summary>
        public string Mobile { get; set; }
    }
}
複製代碼

點擊Ctrl+S而後能夠看到自動生成了一個TextTemplate1.cs文件學習

複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{    public class User
    {
        /// <summary>
        /// 用戶ID
        /// </summary>
        public int UserID { get; set; }

        /// <summary>
        /// 用戶名
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 密碼
        /// </summary>
        public string Password { get; set; }

        /// <summary>
        /// Email
        /// </summary>
        public string Email { get; set; }

        /// <summary>
        /// 手機號
        /// </summary>
        public string Mobile { get; set; }
    }
}
複製代碼

是否是很神奇,T4模版引擎會根據你在模版裏定義的內容自動生成相應的文件,固然本示例過於簡單,徹底不能展示T4的強大,當你若真正瞭解T4後,會發現神馬代碼生成器全都是浮雲,T4纔是王道,利用T4你徹底能夠輕鬆生成屬於本身風格的任何類型代碼,在下篇文章會有實例展現如何經過T4鏈接數據庫自動生成POCO類,基本上這個纔是咱們用T4的最大意圖,呵呵,在這以前仍是老老實實看看枯燥乏味的T4基礎知識吧。測試

T4 文本模板有兩種類型:設計時 T4 文本模板運行時 T4 文本模板(「預處理過的」模板)

  • 設計時模版

  可在應用程序中執行運行時 T4 文本模板(「預處理過的」模板)以便生成文本字符串(一般做爲其輸出的一部分)。ui

  若要建立運行時模板,請向您的項目中添加「已預處理的文本模板」文件。 另外,您還能夠添加純文本文件並將其「自定義工具」屬性設置爲「TextTemplatingFilePreprocessor」。this

  有關更多信息,請參見使用預處理 T4 文本模板生成運行時文本。 有關模板語法的更多信息,請參見編寫 T4 文本模板編碼

  • 運行時模版

  在 Visual Studio 中執行設計時 T4 文本模板,以便定義應用程序的部分源代碼和其餘資源。

  一般,您可使用讀取單個輸入文件或數據庫中的數據的多個模板,並生成一些 .cs、.vb 或其餘源文件。 每一個模板都生成一個文件。 在 Visual Studio 或 MSBuild 內執行它們。

  若要建立設計時模板,請向您的項目中添加「文本模板」文件。 另外,您還能夠添加純文本文件並將其「自定義工具」屬性設置爲「TextTemplatingFileGenerator」。

  有關更多信息,請參見使用 T4 文本模板生成設計時代碼。 有關模板語法的更多信息,請參見編寫 T4 文本模板。 

文本模板由如下部件組成:

  • 指令 - 控制模板處理方式的元素。

  • 文本塊 - 直接複製到輸出的內容。

  • 控制塊 - 向文本插入可變值並控制文本的條件或重複部件的程序代碼。 

T4 文本模板指令

  • T4模版指令 
    <#@ template [language="C#"] [compilerOptions="options"] [culture="code"] [debug="true"] [hostspecific="true"] [inherits="templateBaseClass"] #>
  1. 模版指令中全部特性均爲可選的
  2. langeuage:輸出語言,有效值C#、VB,默認爲C#
  3. debug:是否啓用調試,有效值true、false,默認爲false。特別說明下這個調試真的不咋地,很容易讓VS崩潰,很雞肋的功能,
  4. hostspecific:有效值true、false,默認爲false。若是將此特性的值設置爲 true,則會將名爲 Host 的屬性添加到由文本模板生成的類中。 該屬性是對轉換引擎的宿主的引用,並聲明爲Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost。
  5. inherits:能夠指定模板的程序代碼能夠繼承自另外一個類,這個類也能夠從文本模板生成。目前木有使用過,基本上能夠忽略
  6. compilerOptions:有效值爲任何有效的編譯器選項。基本上能夠忽略 
  • T4 參數指令
    <#@ parameter type="Full.TypeName" name="ParameterName" #>

     顧名思義,就是用來傳參的,應該是用在運行時模版的(預處理模版)

  • T4 輸出指令
    <#@ output extension=".fileNameExtension" [encoding="encoding"] #>

    比較重要的指令,用於設置輸出文件的後綴名和文件編碼
    extension:輸出文件擴展名,默認爲".cs"
    encoding:文件編碼,默值爲utf-8(這裏不能肯定,我測試是utf-8)

  1. 程序集指令至關於VS裏面咱們添加程序集引用的功能,該指令只有一個參數name,用以指定程序集名稱,若是程序集已經在GAC裏面註冊,那麼只須要寫上程序集名稱便可,如<#@ assembly name="System.Data.dll" #>,不然須要指定程序集的物理路徑。
  2. T4模版的程序集引用是徹底獨立的,也就是說咱們在項目中引用了一些程序集,而後項目中添加了一個T4模版,T4模版所須要的全部程序集引用必須明確的在模版中使用程序集執行引用才能夠。
  3. T4模版自動加載如下程序集Microsoft.VisualStudio.TextTemplating.1*.dll、System.dll、WindowsBase.dll,若是用到了其它的程序集須要顯示的使用程序集添加引用才能夠
  4. 可使用 $(variableName) 語法引用 Visual Studio 或 MSBuild 變量(如 $(SolutionDir)),以及使用 %VariableName% 來引用環境變量。介紹幾個經常使用的$(variableName) 變量:

    $(SolutionDir):當前項目所在解決方案目錄

    $(ProjectDir):當前項目所在目錄

    $(TargetPath):當前項目編譯輸出文件絕對路徑

    $(TargetDir):當前項目編譯輸出目錄,即web項目的Bin目錄,控制檯、類庫項目bin目錄下的debug或release目錄(取決於當前的編譯模式)

    舉個例子:好比咱們在D盤根目錄創建了一個控制檯項目TestConsole,解決方案目錄爲D:\LzrabbitRabbit,項目目錄爲
    D:\LzrabbitRabbit\TestConsole,那麼此時在Debug編譯模式下
    $(SolutionDir)的值爲D:\LzrabbitRabbit
    $(ProjectDir)的值爲D:\LzrabbitRabbit\TestConsole
    $(TargetPath)值爲D:\LzrabbitRabbit\TestConsole\bin\Debug\TestConsole.exe
    $(TargetDir)值爲D:\LzrabbitRabbit\TestConsole\bin\Debug\

  • T4 導入指令
    <#@ import namespace="namespace" #>

     在 Visual Studio T4 文本模板的代碼塊中,import 指令容許您在不提供徹底限定名稱的狀況下引用另外一個命名空間中的元素。 它等效於 C# 中的 using 或 Visual Basic 中的 imports。默認已經導入了System命名空間的引用。

  1. filePath 能夠是絕對的,或相對於當前模板文件。
  2. filePath 能夠包括用「%」分隔的環境變量。 例如:<#@ include file="%HOMEPATH%\MyIncludeFile.t4" #>
  3. 所包含的文件的名稱沒必要使用擴展名「.tt」。可能須要針對包含的文件使用其餘擴展名,例如,「.t4」。 這是由於,在您將 .tt 文件添加到項目中時,Visual Studio 會自動將其「自定義工具」屬性設置爲 TextTemplatingFileGenerator。 您一般不但願單獨轉換包含的文件。
  4. 在處理時,被包含內容就像是包含文本模板的組成部分同樣。 不過,即便 include 指令後爲普通文本塊和標準控制塊,也能夠包括含有類功能塊 <#+...#> 的文件。
  5. 包含指令能夠提升代碼複用率,好比咱們能夠將一些經常使用的程序集、命名空間引用放到一個文件裏,使用時僅須要引用下便可,省去了每次都要從新引用一遍的煩惱,如咱們創建Reference.ttinclude文件,裏面包含了咱們平時經常使用的程序集引用
    複製代碼
    <#@ assembly name="System.Core.dll" #>
    <#@ assembly name="System.Data.dll" #>
    <#@ assembly name="System.Data.DataSetExtensions.dll" #>
    <#@ assembly name="System.Xml.dll" #>
    <#@ import namespace="System" #>
    <#@ import namespace="System.Xml" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Data" #>
    <#@ import namespace="System.Data.SqlClient" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ import namespace="System.IO" #>
    複製代碼

    使用時只須要使用包含指令引用下便可

    <#@ include file="$(ProjectDir)Reference.ttinclude"  #>

文本塊

文本塊直接向輸出文件插入文本。 文本塊沒有特殊格式。 例如,下面的文本模板將生成一個包含單詞「Hello World!」的文本文件:

<#@ output extension=".txt" #>
Hello World! 

控制塊 

控制塊是用於轉換模板的程序代碼節。 默認語言是 C#,但若要使用 Visual Basic,能夠在文件開頭編寫如下指令:

<#@ template language="VB" #>

用於編寫控制塊代碼的語言與生成的文本的語言無關。

標準控制塊

標準控制塊是生成輸出文件部件的程序代碼節。
在模板文件中,能夠混合使用任意數量的文本塊和標準控制塊。 可是,不能在控制塊中嵌套控制塊。 每一個標準控制塊都以 <# ... #> 符號分隔。
例如,若是使用下面的控制塊和文本塊,則輸出文件包含行「0, 1, 2, 3, 4 Hello!」:

複製代碼
<#
    for(int i = 0; i < 4; i++)
    {
        Write(i + ", ");
    }
    Write("4");
#> Hello!
複製代碼

您能夠交錯文本和代碼,而沒必要使用顯式 Write() 語句。 如下示例輸出「Hello!」四次: 

複製代碼
<#
    for(int i = 0; i < 4; i++)
    {
#>
Hello!
<#
    } 
#>
複製代碼

在代碼中,可使用 Write(); 語句的位置均可以插入文本塊。 

表達式控制塊

表達式控制塊計算表達式並將其轉換爲字符串。 該字符串將插入到輸出文件中。
表達式控制塊以 <#= ... #> 符號分隔。
例如,若是使用下面的控制塊,則輸出文件包含「5」: 

<#= 2 + 3 #> 

請注意,開始符號有三個字符「<#=」。
表達式能夠包含做用域中的任何變量。 例如,下面的塊輸出數字行:

複製代碼
<#@ output extension=".txt" #>
<#
    for(int i = 0; i < 4; i++)
    {
#>
This is hello number <#= i+1 #>: Hello!
<#
    } 
#>
複製代碼

類功能控制塊

類功能控制塊定義屬性、方法或不該包含在主轉換中的全部其餘代碼。 類功能塊經常使用於編寫幫助器函數。 一般,類功能塊位於單獨的文件中,這樣它們能夠包含在多個文本模板中。
類功能控制塊以 <#+ ... #> 符號分隔,能夠簡單的認爲<#+ ...#>定義的內容爲咱們的類文件
例如,下面的模板文件聲明並使用一個方法:

複製代碼
<#@ output extension=".txt" #>
Squares:
<#
    for(int i = 0; i < 4; i++)
    {
#>
    The square of <#= i #> is <#= Square(i+1) #>.
<#
    } 
#>
That is the end of the list.
<#+   // Start of class feature block
private int Square(int i)
{
    return i*i;
}
#>
複製代碼

類功能必須編寫在文件末尾。 不過,即便 include 指令後跟標準塊和文本,也能夠 <#@include#> 包含類功能的文件。
類功能塊能夠包含文本塊
能夠編寫生成文本的方法。 例如:
List of Squares:

複製代碼
<#
   for(int i = 0; i < 4; i++)
   {  WriteSquareLine(i); }
#>
End of list.
<#+   // Class feature block
private void WriteSquareLine(int i)
{
#>
   The square of <#= i #> is <#= i*i #>.
<#   
}
#>
複製代碼

將文本生成方法放置在可供多個模板包含的單獨文件中,是很是有用的。

嗯,大概的基礎點應該就這些了,更多的本身去MSDNhttp://msdn.microsoft.com/zh-cn/library/bb126445詳細瞭解吧

  這裏解釋點容易讓人困惑的地方,咱們在T4模版裏面引用的程序集和那些命名空間都是利用T4生成代碼須要使用的,也就是T4模版要用的,和咱們要生成的目標類毛關係都沒有,當初爲搞清楚這點但是費了不精力。T4初看起來很複雜,其實稍微花些心思研究下,主要彷佛把MSDN看懂仍是很容易學會的,一旦掌握了受用無窮

相關文章
相關標籤/搜索