你必须懂的 T4 模板:体系架构

2 篇文章 0 订阅

  =============C#.Net 篇目录==============

         T4文本模板,即一种自定义规则的代码生成器。根据业务模型可生成任何形式的文本文件或供程序调用的字符串。(更多基础知识请参见《你必须懂的 T4 模板:深入浅出》

         文本模板运行在 Visual Studio 本身提供的一套基于T4模板引擎中,只有了解 T4 模板引擎的运作才能让你更好地使用 T4 ,并在适当的时候进行重写自定义。(如下针对“设计时模板”转换过程进行说明)

 

VS本身只提供一套基于T4引擎的代码生成的执行环境,由下面程序集构成:

Microsoft.VisualStudio.TextTemplating.10.0.dll
Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.dll
Microsoft.VisualStudio.TextTemplating.Modeling.10.0.dll
Microsoft.VisualStudio.TextTemplating.VSHost.10.0.dll

T4 模板引擎 dll 反编译源代码这里下载。

 

模板转换过程

         这里提供一幅协作图,用于阐释模板转换过程及该过程中各个参与对象。下面的段落将一步一步解释文本转换过程。

image

 

1.         Custom Tool

    模板转换过程起点:在 Visual Studio 的解决方案资源管理器中右击模板文件 (.tt) 并在弹出的上下文菜单中选择“运行自定义工具”。(更多启动方式)

    自定义工具是一个实现了 Visual Studio 定义的IVsSingleFileGenerator接口的特殊组件。T4 自定义工具由Microsoft.VisualStudio.TextTemplating.VSHost.TemplatedCodeGenerator类实现并且在注册表中注册在Visual Studio 下命名为TextTemplatingFileGenerator。Visual Studio 将使用该名称查找自定义工具、创建 COM 对象并调用其IVsSingleFileGenerator.Generate 方法。step 1

a)         IVsSingleFileGenerator  

   任何一个 Custom tool 必须实现该接口,其Generate方法执行将单个输入文件转化为能被编译或可添加到项目中的单个输出文件。

b)         注册表:

          HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Generators

          image

          image

 

2.         ITextTemplateing Service

    自定义工具使用 Visual Studio 提供的Microsoft.VisualStudio.OLE.Interop.IServiceProvider.QueryServic() 方法来定位 T4 提供的ITextTemplating服务。ITextTemplating服务由Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService实现。一旦定位到服务,自定义工具调用ITextTemplating.ProcessTemplate方法,并传递相应的模板内容和参数。step 1.1

IServiceProvider定义

namespace Microsoft.VisualStudio.OLE.Interop

{

    [Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]

    [InterfaceType(1)]

    publicinterfaceIServiceProvider

    {

           intQueryService(refGuidguidService, refGuidriid, outIntPtrppvObject);

    }

}

 

方法步骤1:

IVsSingleFileGenerator.Generate() ->GenerateCode() ->ITextTemplating.ProcessTemplate()

image

image

 

3.         Host

    Microsoft.VisualStudio.TextTemplating.VSHost.10.0.dll 的TextTemplatingService服务实现Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost接口,为代码生成引擎提供 Host (宿主)。在模板转换过程中: Engine 负责代码生成;Host负责提供转换过程中行为具体实现及所需要的的所有外部资源,ITextTemplatingEngineHost和模板内容一起传递到Engine.ProcessTempalte方法中用于代码生成。step 1.2

方法步骤2:

ITextTemplating.ProcessTemplate()–>ITextTemplatingEngine.ProcessTemplate()

image

 

4.         Engine

    T4 引擎负责解析模板step2,生成并编译GeneratedTextTransformation类steps3,4,5,运行生成类的TransformText() 并将输出内容返回给 Host step 6。解析模板内容后step 2,引擎开始处理用于模板的 T4 指令。当处理内置指令时step 3,引擎调用 Host 相应方法来执行所需的操作,eg:引擎通过调用 Host 的ITextTemplatingEngineHost.LoadIncludeText方法来处理 include 指令step 3.1

由图可清晰知道:Engine是模板转换过程中主要对象,解析模板、处理指令、编译生成类等等。

image

方法步骤3:

ITextTemplatingEngine.ProcessTemplate() ->Engine.ProcessTemplateImplementation() ->Engine.CompileAndRunCode()

image

image

 

5.         DirectiveProcessor

    当处理自定义指令时step 4,引擎首先调用 Host 的ITextTemplatingEngineHost.ResolveDirectiveProcessor来确定每个DirectiveProcessor(具体指令处理器的抽象基类)的类型step 4.1。指令处理器通过在生成的GeneratedTextTransformation类中添加代码进行工作。Eg:<#@ parameter #> 指令创建一个属性用于模板与外部的参数传递(更多请参见《(译)理解 T4 模板:<#@ parameter #> 指令》)。一旦处理器确定所有自定义指令的类型后,该引擎实例化并为每个自定义指令调用其对应处理器的DirectiveProcessor.ProcessDirective方法step 4.2)。

 

6.         GenerateTextTransformation

         Engine 组合解析的模板块和自定义指令来生成GeneratedTextTransformation类,这个类继承自Microsoft.VisualStudio.TextTemplating.TextTransformation类step 5

         Engine 调用Host 的ITextTemplatingEngineHost.ResolveAssemblyReference方法查找模板引用的所有程序集并进行编译step 5.1。然后再调用 Host 的ITextTemplatingEngineHost.ProvideTemplatingAppDomain方法来获取运行所生成转换类的应用程序域step 5.2。Visual Studio 宿主将创建一个命名为“TemplatingAppDomain”新AppDomainstep 5.3.如果“TemplatingAppDomain域”已经存在,Visual Studio 宿主将重用它。

         获得TemplatingAppDomain之后,Engine 使用CodeDomProvider将生成的GeneratedTextTransformation类编译到一个内存中的临时程序集step 5.4。临时程序集会缓存在TemplatingAppDomain中,如果再次转换相同的模板,Engine将从缓存中查找而不是重新生成一个。

         一旦GeneratedTextTransformation编译好,Engine创建此类的实例并调用TransformText方法step 6。TransformText方法返回由模板生成的内容,并传回到Engine,Host,Custom Tool 最后传递到 Visual Studio。

 

说说 T4 体系的优劣

1.         T4 旨在设计用于生成输出文件的模板

    由前面几节讲述IVsSingleFileGenerator.Generate()到ITextTemplating.ProcessTemplate()可知Custom Tool仅仅负责生成内容。Custom Tool 返回生成的内容到 Visual Studio ,由Visual Studio将内容保存到文件并将输出文件添加到当前项目并将其做为源代码的管理。这一伟大设计并不需要 custom tool 对Visual Studio 内核深入了解,但是,也限制了每个 T4 模板只能生成单个输出文件。T4 模板需要使用特殊的变通方法来从单个模板生成多个输出文件。(生成多个文件这块涉及到示例,后续我整示例程序的时候再整理生成多个文件的方法,有兴趣的先看老外原文

 

2.         在 Visual Studio 加载项中,可以使用ITextTemplating服务

    使用ITextTemplating服务并不只限于 T4 自定义工具。也可以直接从 Visual Studio 加载此服务(引用Microsoft.VisualStudio.TextTemplating.10.0.dll )。例如,DSL 设计器能直接通过域模型使用一个或多个“独立模板”生成代码,而不需要用户添加和管理项目中的 .tt文件。

a)         DSL(Domain-Specific Languages 领域特定语言)

是指软件开发中出于某特定考虑而设计的小的、目标明确的语言。它们的作用是,使用某特定领域里惯用的符号或者表示法对该领域的实体或者流程进行建模。这就是它们区别于那些提供统一符号表示的通用建模语言(如UML)的地方。另外一个区别是UML经常被用作于文档分析或者设计交付,而领域特定语言既可以用作建模工具,还可以用作代码生成器(代码生成是基于TextTemplate(.tt)文件的)。

b)         独立模板

是一个可以重复使用的模板,可变部分通过参数进行传入。Eg:模板A在调用模板B时(Microsoft.VisualStudio.TextTemplating.Engine.ProcessTemplate()),模板A将需要的参数值做为CallContext或Session 传递给模板B的<#@ parameter>,并且使用 T4 引擎为模板B生成中间代码并运行输出结果。示例可参考《(译)理解 T4 模板:<#@ parameter #>指令》

 

3.         通过实现自定义 Host 改变内置指令的行为

    请记住,Engine处理内置指令无需额外创建指令处理器。Eg:<#@output #>指令调用ITextTemplatingEngineHost .SetFileExtension和ITextTemplatingEngineHost .SetOutputEncoding方法。要改变内置指令的行为你必须创建自定义的宿主(实现ITextTemplatingEngineHost)。

 

4.         在不同宿主中 T4 指令的行为存在差异

    创建自定义 T4 宿主的能力是一把双刃剑。因为不同宿主的实现提供的功能差别很大(eg:Microsoft-Visual Studio 和 TextTransform.exe 命令行工具),影响了如assembly,include等指令的行为,所以相同的模板很难重用在不同的宿主上。

 

5.         通过自定义指令扩展 T4 模板语法

    你能为 T4 模板创建一个自定义指令处理器并通过设置注册表项注册指令处理器。不幸的是,TextTransform.exe 命令行工具不支持相同的注册机制,可能会限制你使用自定义指令的能力。

 

6.         T4 模板引入的程序集将被锁定

    在 Visual Studio 中重用“TemplatingAppDomain域”能提高性能,不幸的是,这是要付出代价的。一旦包含GeneratedTextTransformation类的程序集(eg:程序集A)加载到“TemplatingAppDomain域”中,.NET Framework 会锁定当前引用的所有程序集(包括程序集A)。如果你的模板放在这些将被锁定的程序集中,那么在运行模板后这些程序集将因锁定而无法重编译。还存在一个问题,你的模板不能直接从被锁定的程序集中调用执行代码,但是可以通过反射或CodeModel简单的访问类型元素据。

 

7.         在 Visual Studio 进程中运行的GeneratedTextTransformation

最后,GeneratedTextTransformation加载到“TemplatingAppDomain域”并运行在 Visual Studio 进程中(devenv.exe)。这种设计的两个副作用

a)         调试的时候必须启动另外一个 Visual Studio 实例来进行断点调试。

b)         Visual Studio 进程定义Environment.CurrentDirectory来运行GenerateTextTransformation,不匹配模板本身所在的位置。这使得在 T4 模板中更难以使用相对路径来引用外部文件,可在 T4 模板中使用ITextTemplatingEngineHost. ResolvePath方法来解决此问题。

 

8.         在模板中访问宿主

    通过在<#@ template #>指令中添加hostspecific=”True”属性使可在模板中访问宿主。GeneratedTextTransformation类中会生成一个 Host 属性提供给模板访问。Eg,在模板中使用this.Host.ResolvePath() 将相对路径转化为绝对路径。

 

9.         在模板中访问 Visual Studio 服务

Visual Studio Host实现了IServiceProvider接口,可以通过强制类型转换ITextTemplatingEngineHost接口实例 Host来得到IServiceProvider接口实例。通过IServiceProvider.GetService() 方法可以访问 Visual Studio 提供的服务。

         Eg:

               IServiceProviderserviceProvider = (IServiceProvider)this.Host;

               EnvDTE.DTEdte = (EnvDTE.DTE) serviceProvider.GetService(typeof(EnvDTE.DTE));

 

本想整个示例的,发现还有诸多不便,了解了一些在示例中可能会用到的优雅方案,所以接下来会整理:1、单个模板生成多个文件; 2、自定义模板指令; 3、示例   (有兴趣的园友可以关注下我,以方便得到最新信息)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: VS Code T4 模板是一种用于生成 JavaScript 代码的工具。它基于 T4Text Template Transformation Toolkit)技术,允许开发者定义模板并在生成代码时将其应用于指定的数据。 使用 VS Code T4 模板生成 JavaScript 代码非常简单。首先,我们需要安装 "T4" 扩展插件,该插件提供了 T4 模板引擎的支持。安装完成后,我们可以创建一个新的 T4 模板文件,并在其中编写模板代码。 T4 模板使用一种特殊的标记语法,类似于 HTML 的标签。我们可以在模板中定义变量、循环、判断等逻辑,并根据需要生成相应的 JavaScript 代码。模板还可以包含外部引用的文件或库,以便在代码生成过程中使用。 一旦模板编写完成,我们可以在模板文件上右键点击,并选择 "运行 T4 模板" 选项,或使用命令面板搜索并运行相应命令。这将触发模板引擎执行,根据模板和提供的数据生成 JavaScript 代码。 T4 模板可以根据我们定义的逻辑和数据生成任意数量的 JavaScript 代码文件。这为我们提供了一种自动化生成重复代码的方式,在项目开发中可以极大地提高效率和代码质量。 总之,VS Code T4 模板提供了一种方便的方式来生成 JavaScript 代码。通过定义模板和提供相应的数据,我们可以自动生成符合需求的 JavaScript 代码,减少重复工作并提高开发效率。无论是创建新项目、添加新功能还是生成测试数据,T4 模板都能为我们提供一种强大的辅助工具。 ### 回答2: VSCode是一款功能强大的文本编辑器,它提供了许多扩展插件,其中包括T4模板生成JS。T4模板是一种用于生成代码的模板引擎,它使用C#或VB.NET编写模板代码,并通过内置的代码生成引擎将模板代码转换为最终的输出。 在VSCode中使用T4模板生成JS非常简单。首先,我们需要安装T4模板插件。可以通过在VSCode的扩展商店中搜索"T4 Template"来找到并安装这个插件。安装完成后,我们可以在VSCode的侧边栏中找到T4模板生成器的图标。 接下来,我们需要创建一个T4模板文件。可以使用`.tt`作为扩展名来命名文件,并打开该文件进行编辑。在模板文件中,我们可以使用C#或VB.NET编写代码块,并使用特定的语法来控制模板生成的过程。我们可以定义输入参数、循环结构、条件语句等,以生成不同的输出内容。 在T4模板中生成JS代码的过程与生成其他类型的代码并无太大区别。我们可以在模板中定义JS变量、函数、类等,并使用T4模板提供的代码生成功能来生成相应的JS代码。 当模板文件中的代码编写完成后,我们可以保存文件并触发模板生成过程。在VSCode的命令面板中,输入"T4 Template"并选择生成模板命令,就可以将模板文件转换为对应的JS代码文件。 总结来说,使用VSCode的T4模板插件可以方便地生成JS代码。我们只需要编写模板文件,定义所需的JS代码结构和逻辑,然后由T4模板生成器自动转换为最终的JS代码文件。这样,我们可以更高效地生成大量的JS代码,并减少手工编写的工作量。 ### 回答3: VSCode是一款功能强大的代码编辑器,它支持通过T4模板生成JavaScript代码。 T4模板是一种文本生成引擎,它允许我们根据定义的模板规则生成特定的代码文件。在VSCode中使用T4模板生成JavaScript代码可以提高开发效率和代码质量。 首先,我们需要安装VSCode的T4模板插件,可以在VSCode的插件市场中搜索并安装。安装完成后,我们可以在VSCode的扩展面板中找到并启用T4模板相关功能。 接下来,在VSCode中创建一个新的文件,并将其命名为T4模板文件,通常以.tt作为文件扩展名。在T4模板文件中,我们可以使用类似于ASP.NET的标签语法来定义模板中的输入和输出。 在模板文件中,我们可以定义输入参数,例如要生成的JavaScript文件的名称和路径。然后,可以使用T4模板提供的标签和指令,通过循环、条件语句和字符串操作等方式来生成JavaScript代码。 使用T4模板生成JavaScript代码的好处是我们可以根据不同的需求和条件生成不同的代码。这样可以提高代码的可维护性和复用性。同时,T4模板还支持自定义函数和引用外部库,可以更灵活地生成JavaScript代码。 最后,我们可以通过执行模板文件来生成JavaScript代码。在VSCode中,我们可以打开T4模板文件,右键点击并选择“转换为输出文件”,这将会根据模板文件的定义生成相应的JavaScript代码文件。 总结起来,通过VSCode的T4模板插件,我们可以方便地生成JavaScript代码。通过定义模板规则和执行模板文件,我们可以根据需求快速生成高质量的JavaScript代码。这对于JavaScript开发者来说是一个非常有用的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值