我正在尝试编写一个控制台程序,它将T4模板的文件名作为参数,然后处理该模板。这是因为我希望用户能够更新模板而无需重新编译程序。
我找到的最简单的解决方案是在Visual Studio中创建第二个模板,该模板预编译为C#类,后者又执行我的外部模板“Template.tt”:
<#@ template language="C#" hostspecific="True" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#
string template = File.ReadAllText(Host.ResolvePath("Template.tt"));
Engine engine = new Engine();
string output = engine.ProcessTemplate(template, Host);
Write(output);
#>
在我的控制台程序的Program.cs中,我然后执行这个“调用”模板:
string templateText = new Caller().TransformText();
问题是当我运行它(F5)时,它会在我的调用者模板的第一行抛出NullReferenceException,因为Host为null。
但是,我认为将hosts特定设置为True会给我一个主机。
获取主持人需要做什么?真的不想自己动手。 或者,是否有更好的方法来执行外部T4模板?
答案 0 :(得分:0)
根据MSDN documentation,hostspecific属性仅提供对t4模板内Host-Property的访问。它不保证主机的存在。对于设计时模板(在visual studio中进行转换),Visual Studio和它的T4引擎提供了这个主机。不幸的是,Microsoft.VisualStudio.TextTemplating.dll不是可再发行的程序集。因此,您不会在运行时方案中拥有该主机。
如你所说,你需要编写一个完整的T4引擎并自己托管......
如果您的用户需要编写/更改t4模板,他们就具备编程和编写文本模板的知识。你能想出一种让他们以任何方式使用visual studio的方法吗?
或者(如果用户所做的更改很小),您可以尝试使用适用于其他输入的预编译模板(xml文件,ini文件,命令行参数,......)。
抱歉没有更好的消息......
答案 1 :(得分:0)
实际的自定义(基于命令行的应用程序)T4主机并不太难实现,我不记得我的代码,但这里是我们的T4模块化控制台 - 应用程序运行的链接: https://github.com/abstractiondev/absbuilder
实际的命令行主机在这里: https://github.com/abstractiondev/absbuilder/blob/master/AbstractionBuilder/CustomCmdLineHost.cs
为了引用T4部件,我们已经在Linux中使用Mono运行时/ MonoDevelop环境运行工具,现在基于测试(那是1 - 2年前),我记得MonoDevelop的T4是完全兼容的并且作为源提供代码有一些非常合理的许可(麻省理工学院或Apache 2.0,如果我没记错的话)。