T4 简介
T4,全称 Text Template Transformation Toolkit,早在 VS2005 中就存在的东西,只是没有高度集成,VS2010 在托管项目中新增了添加 Text Template 文件的模板,但是并没有代码颜色和智能感知,可以说它是 Visual Studio 一个“隐藏”的特性。T4 一般用来从某种“模型”自动生成好用的代码,例如从XML模型生成操作它的强类型代码。不知道是不是 C++ 的宏和模板实在太强大,貌似这种代码生成器用在托管语言中用得广泛多,其实我想在 C++ 中用这个也是跟托管程序有关。
一般来说,在托管的项目中添加一个 .tt 后缀名的文本文件即可用到 T4,如图:
对于生成什么扩展名的文件,其实并没有限制,可以在 .tt 文件的处理指令中指定:
<#@ template language="C#" #>
<#@ output extension=".generated.cs" #>
然后就基本好像写 PHP 或者 ASP 那样了,不同之处在于 T4 的生成步骤是在一个方法中的,如果要自定一些帮助函数,需要用 <#+ 和 #> 包围。参见 MSDN 上一个简单的例子:Walkthrough: Generating Code by using Text Templates。
尝试在 C++ 项目中添加
第一步,肯定要先添加一个 .tt 文件。很不幸地发现,魔法没有自动出现,.tt 文件是在那里了,但是没有自动生成的文件,IDE 也没有显示什么文件跟这个 .tt 有关联关系。很显然,需要告诉 IDE 更多事情。
其实在尝试这个东西之前,我是有想过最终的成功率的,根据我的了解,1) Visual Studio 使用 MSBuild 的项目文件,2) VS2010 构建 C++ 项目使用 MSBuild,3)T4 可以作为 MSBuild 中的一个 Custom Build Tool 介入。从这三点理解的话,可知只要修改项目文件,即使 VS 不支持某些东西,只要它不乱改我们在项目文件中的设置,就可以保证构建的项目是正确的。
有了上面的知识,可以开始下一步的尝试了:新建一个 C# 项目,添加一个 .tt 文件,然后观察项目文件如何变化,其实稍微了解 MSBuild 项目文件的结构是怎么样的话,很快就知道了。我的项目需要的是根据“旧的”文件自动生成上万个包装函数,而这个“旧的”意思是,这个文件会在其他社区不断地更新,增加更多函数,我做了这个自动生成的就无需每次都根据新文件手动查找替换修改了。于是我修改成这个样子:
<!-- Items that use T4 -->
<ItemGroup>
<None Include="Scripting.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<FileType>Asax</FileType>
</None>
<ClInclude Include="Scripting.h">
<AutoGen>True</AutoGen>
<DependentUpon>Scripting.tt</DependentUpon>
<DesignTime>True</DesignTime>
</ClInclude>
<None Include="Scripting_.h" />
</ItemGroup>
其实,这段东西的重点在于,.tt 有一个 Generator 子标签,内容是 TextTemplatingFileGenerator,标签 None 它表示不参与到 Build 中,只是 T4 用的。ClInclude 表示我生成的 .h 文件在 Build 过程中是头文件,AutoGen 表示这个文件由工具自动生成,DependentUpon 可以使 Visual Studio 知道这两个家伙有联系。
现在重新载入项目,可以看到 Visual Studio 将他们关联了,但是赶出了 Header Files,而我就将它们放到一个新的 Filter 中去:
快搞定了!
但是我们拿这个编辑过的项目文件构建的时候,并没有看到有输出文件。也就是说,T4 其实还没有介入。而在托管的项目中,当你保存 .tt 文件的时候,或者点击 Solution Explorer 上运行 Transform 的时候,T4 引擎就会自动运行生成输出,如果你改变 output 指令的 extension 参数,输出文件的扩展名还会自动更改,确切地说,旧的文件会被移到回收站。正当我快要放弃的时候,突然发现 MSDN 文档中有一节:Code Generation in a Build Process,其中表示,只要装上 Visual Studio Visualization and Modeling SDK 然后在项目文件差不多最后的地方加上以下代码即可:
<!-- Enable TransformOnBuild for Msbuild -->
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" />
<PropertyGroup>
<TransformOnBuild>True</TransformOnBuild>
</PropertyGroup>
噢,终于胜利了!最后发现,仍然不能直接只在 .tt 文件中修改输出指令的 extension 参数,VS 不会帮你自动更改,需要自己动手修改项目文件,不过这个就无所谓了,因为我的目的达到了,思想也验证了。
最后附上示例项目文件。
posted on 2010-08-17 04:05
DiryBoy 阅读(3331)
评论(2) 编辑 收藏 引用