T4文本模板轉換過程


T4文本模板轉換過程將文本模板文件作為輸入,生成一個新的文本文件作為輸出。 例如,可以使用文本模板生成 Visual Basic 或 C# 代碼,還可以生成 HTML 報告。

有三個組件參與這一過程:引擎宿主指令處理器。 引擎對該過程進行控制(引擎與宿主和指令處理器交互),以生成輸出文件;宿主提供與環境的所有交互(如定位文件和程序集); 指令處理器為文本模板添加功能(如從 XML 文件或數據庫讀取數據等)。

組件:

組件 說明 可自定義(是/否)
引擎 引擎組件控制文本模板轉換過程。
主機 宿主是引擎與用戶環境之間的接口。 Visual Studio 是文本轉換過程的宿主。 是。 可以編寫自定義宿主。
指令處理器 指令處理器是處理文本模板中的指令的類。 可以使用指令從輸入源向文本模板提供數據。 是。 可以編寫自定義指令處理器。

引擎:

引擎以字符串形式從宿主接收模板,而宿主處理在轉換過程中所用的所有文件。 接下來,引擎請求宿主定位所有自定義指令處理器和環境中的其他方面。 然后,引擎編譯和運行生成轉換類。 引擎將生成的文本返回給宿主,宿主通常將該文本保存到文件中。

宿主:

宿主負責轉換過程之外與環境有關的所有操作,包括:

1)查找引擎或指令處理器請求的文本和二進制文件。 宿主可以搜索目錄和全局程序集緩存以查找程序集。 宿主可以為引擎查找自定義指令處理器代碼。 宿主還可以查找並讀取文本文件,然后以字符串形式返回其內容。

2)提供標准程序集和命名空間的列表,供引擎用於創建生成轉換類。

3)提供引擎在編譯和執行生成轉換類時所用的應用程序域。 將使用獨立應用程序域,以免宿主應用程序受到模板代碼錯誤的影響。

4)寫入生成的輸出文件。

5)設置生成的輸出文件的默認擴展名。

6)處理文本模板轉換錯誤。 例如,宿主可以將錯誤顯示在用戶界面中,也可以將錯誤寫入文件。 (在 Visual Studio 中,錯誤顯示在“錯誤消息”窗口中。)

7)在用戶調用了指令但未提供值時,提供必需的參數值。 指令處理器可以指定指令名稱和參數,可以請求宿主提供默認值(如果有)。

指令和指令處理器:

指令是文本模板中的命令。 它向生成過程提供參數。 通常,指令定義模型或其他輸入的源和類型,以及輸出文件的文件擴展名等。

指令處理器可以處理一個或多個指令。 轉換模板之前,必須安裝能夠處理模板中的指令的指令處理器。


有了基本的概念,我們看下面的Demo(在程序中動態執行T4模板):


在程序中動態執行T4模板:

執行結果:

image

CustomTextTemplatingEngineHost.cs(自定義文本模板宿主‎

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TextTemplating;
using System.CodeDom.Compiler;
using System.IO;
 
namespace CustomHost
{
    public class CustomTextTemplatingEngineHost : ITextTemplatingEngineHost, ITextTemplatingSessionHost
    {
        #region ITextTemplatingEngineHost
        internal string TemplateFileValue;
        public string TemplateFile
        {
            get { return TemplateFileValue; }
        }
       
        private string fileExtensionValue = ".txt";
        public string FileExtension
        {
            get { return fileExtensionValue; }
        }
        
        private Encoding fileEncodingValue = Encoding.UTF8;
        public Encoding FileEncoding
        {
            get { return fileEncodingValue; }
        }
        private CompilerErrorCollection errorsValue;
        public CompilerErrorCollection Errors
        {
            get { return errorsValue; }
        }
        public IList<string> StandardAssemblyReferences
        {
            get
            {
                return new string[]
                {
                    typeof(System.Uri).Assembly.Location
                };
            }
        }
        public IList<string> StandardImports
        {
            get
            {
                return new string[]
                {
                    "System"
                };
            }
        }
        public bool LoadIncludeText(string requestFileName, out string content, out string location)
        {
            content = System.String.Empty;
            location = System.String.Empty;
 
            if (File.Exists(requestFileName))
            {
                content = File.ReadAllText(requestFileName);
                return true;
            }
            else
            {
                return false;
            }
        }
        
        public object GetHostOption(string optionName)
        {
            object returnObject;
            switch (optionName)
            {
                case "CacheAssemblies":
                    returnObject = true;
                    break;
                default:
                    returnObject = null;
                    break;
            }
            return returnObject;
        }
       
        public string ResolveAssemblyReference(string assemblyReference)
        {
            if (File.Exists(assemblyReference))
            {
                return assemblyReference;
            }
           
            string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), assemblyReference);
            if (File.Exists(candidate))
            {
                return candidate;
            }
            return "";
        }
        
        public Type ResolveDirectiveProcessor(string processorName)
        {
            if (string.Compare(processorName, "XYZ", StringComparison.OrdinalIgnoreCase) == 0)
            {
                //return typeof();
            }
            throw new Exception("Directive Processor not found");
        }
       
        public string ResolvePath(string fileName)
        {
            if (fileName == null)
            {
                throw new ArgumentNullException("the file name cannot be null");
            }
            if (File.Exists(fileName))
            {
                return fileName;
            }
            string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), fileName);
            if (File.Exists(candidate))
            {
                return candidate;
            }
            return fileName;
        }
 
        public string ResolveParameterValue(string directiveId, string processorName, string parameterName)
        {
            if (directiveId == null)
            {
                throw new ArgumentNullException("the directiveId cannot be null");
            }
            if (processorName == null)
            {
                throw new ArgumentNullException("the processorName cannot be null");
            }
            if (parameterName == null)
            {
                throw new ArgumentNullException("the parameterName cannot be null");
            }
            return String.Empty;
        }
 
        public void SetFileExtension(string extension)
        {
            fileExtensionValue = extension;
        }
        
        public void SetOutputEncoding(System.Text.Encoding encoding, bool fromOutputDirective)
        {
            fileEncodingValue = encoding;
        }
        
        public void LogErrors(CompilerErrorCollection errors)
        {
            errorsValue = errors;
        }
       
        public AppDomain ProvideTemplatingAppDomain(string content)
        {
            return AppDomain.CreateDomain("Generation App Domain");
        }
 
        #endregion
 
        #region ITextTemplatingSessionHost
        public ITextTemplatingSession CreateSession()
        {
            return Session;
        }
 
        public ITextTemplatingSession Session
        {
            get;
            set;
        }
        #endregion
    }
}

“執行”按鈕單擊-》(T4文本模板轉換過程

CustomTextTemplatingEngineHost host = new CustomTextTemplatingEngineHost();
host.TemplateFileValue = txtPath.Text;
string input = File.ReadAllText(txtPath.Text);
host.Session = new TextTemplatingSession();
host.Session.Add("hzx", new People("韓兆新", 24, "男"));
 
string output = new Engine().ProcessTemplate(input, host);
 
txtResult.Text = output;
StringBuilder errorWarn = new StringBuilder();
foreach (CompilerError error in host.Errors)
{
    errorWarn.Append(error.Line).Append(":").AppendLine(error.ErrorText);
}
txtError.Text = errorWarn.ToString();

申明People類可序列化(傳遞參數的類型)

[Serializable]
public class People
{
    public People(string name, uint age, string sex)
    {
        this.Name = name;
        this.Age = age;
        this.Sex = sex;
    }
    public string Name
    { set; get; }
    public uint Age
    { set; get; }
    public string Sex
    { set; get; }
}

test.tt

<#@template debug="false" hostspecific="false" language="C#"#>
<#@ output extension=".txt" encoding="utf-8" #>
<#@ parameter type="Demo_T4.People" name="hzx" #>
Name:<#= hzx.Name #>  Age:<#= hzx.Age #>   Sex:<#= hzx.Sex #>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM