T4模板和运行时参数
我正在 VS 2010 中构建一个插件,但我陷入了 T4 一代。 现在,我已经实现了(就像 MSDN 建议的那样)一个自定义 T4 主机来生成我的 T4 结果,并且我以这种方式使用它:
const string content = @"c:\Simple.tt";
var engine = new Engine();
var host = new MyTemplateHost();
var result = engine.ProcessTemplate(File.ReadAllText(content), host);
foreach (CompilerError error in host.Errors)
{
Console.WriteLine(error.ErrorText);
}
直到我在模板中传递参数为止,它都有效。一旦我在 .tt 文件中创建参数,主机就会惊慌失措地说它不知道如何解析它。 我看到你可以使用 TemplateSession 来做到这一点,但我不知道如何将它传递给我的主机? 是否有更好的方法使用 C# 从 .tt 生成代码并在运行时传递参数?也许我走错了路。
I am building a plug-in in VS 2010 and I get stuck at the T4 generation.
Right now I have implemented (like MSDN suggests) a custom T4 host to generate my T4 results and I use it in this way:
const string content = @"c:\Simple.tt";
var engine = new Engine();
var host = new MyTemplateHost();
var result = engine.ProcessTemplate(File.ReadAllText(content), host);
foreach (CompilerError error in host.Errors)
{
Console.WriteLine(error.ErrorText);
}
This works until I pass a parameter in the Template. As soon as I create a parameter in the .tt file, the Host freak out saying that it doesn't know how to resolve it.
I saw that you can use the TemplateSession to do that but I didn't figure out how to pass it to my Host?
Is there a better way of generating code from a .tt using C# and passing parameters at run-time? Maybe I am on the wrong path.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在 Visual Studio 2010 中,T4 模板引擎发生了根本性的变化。
现在您可以直接运行模板文件并向其传递您想要的任何参数类型。
该语句将处理以下模板:
所以说实话,不再需要主机了......
Within Visual Studio 2010 the T4 template engine has been radically changed.
Now you can run directly a template file and pass to it any parameter type you want.
This statement will process the following template:
So honestly the host is not really needed anymore ...
如果您正在为 VS 构建加载项,您可能不需要自定义主机,而是可以通过其服务接口使用内置 VS 主机。
查看 ITextTemplated 作为核心服务 API,您可以通过将 DTE 对象强制转换为 IServiceProvider,然后调用 GetService(typeof(STextTemplated))
来获取要传递参数,然后可以将 ITextTemplated 对象侧向强制转换为 ITextTemplatedSessionHost 并将 Session 属性设置为 ITextTemplatedSession。会话本质上只是一个可序列化的属性包。有一个简单的会话,以 TextTemplatedSession 的形式提供。
If you are building an add-in for VS, you probably don't need a custom host, but can instead use the built-in VS host via its service interface.
Check out ITextTemplating as the core service API, which you can get by casting your DTE object to an IServiceProvider, then calling GetService(typeof(STextTemplating))
To pass parameters, you can then sidecast the ITextTemplating object to ITextTemplatingSessionHost and set the Session property to an implementation of ITextTemplatingSession. A session is essentially just a serializable property bag. There's a trivial one provided as TextTemplatingSession.
将 ITextTemplateSessionHost 添加并实施到您的自定义主机。仅实现 ITextTemplateEngineHost 不会为您提供会话支持。
Add and implement the ITextTemplatingSessionHost to your custom host. Just implementing the ITextTemplatingEngineHost won't give you session support.
使用 T4 模板进行运行时生成
如果您需要在运行时生成代码,请选择此方法。例如,您想使用 Selenium 生成页面对象。
在您的解决方案中创建一个文件夹,将其命名为 Templates(适合用于
T4 模板)。
接下来添加一个类型为 T4 的新项目,然后选择
运行时文本模板...我们将模板命名为 MyNodeName.tt,如上图所示。
添加您的代码,如下所示,顶部部分由 Visual Studio 插入...
您可以看到我们想要传递命名空间和类名(这些是上面看到的 Model.NameSpaceName 和 Model.ClassName 标记。
棘手的部分是学习如何传递参数...
创建一个名为partial的新CS类在文件名中
。 alt="Partial File Name">
但在类中不要将其命名为 MyNodeNamePartial,将其命名为 MyNodeName,如下所示:
这与创建自己的部分类的 TT 文件 (MyNodeName) 同名。请注意,我们有一个名为 MODEL 的此类类型的值。
模型类包含 ClassName 和 NameSpaceName 以及您想要“注入”到模板中的任何其他内容。
此工作的关键如图所示,
是使用了运行时文本模板!如果您使用文本模板,无论您做什么,您都会看到类似于“找不到模型”的错误或其他不明确的问题。
调试技巧:
“无法找到模型”是 T4 生成代码,告诉您在带有名为 MODEL 的变量的部分类中,它无法找到它!检查您的部分类型和模型类型,以确保它们与在该文件夹中创建的任何其他普通类命名空间位于同一命名空间中。
Using T4 Templates for Run Time Generation
You choose this method if you need to generate code at run-time. For example you want to generate a Page Object using Selenium.
Create a folder in your solution, name it Templates (good name for
T4 Templates).
Next add a new Item, of type T4, then pick the
Runtime Text Template.... We named our template MyNodeName.tt which is seen in the image above.
Add your code as shown below, the top part was inserted by Visual Studio...
You can see that we want to pass in the Namespace and ClassName (these are the Model.NameSpaceName and Model.ClassName markup seen above.
The tricky part is learning how to pass in the parameters...
Create a new CS class with the name partial in the file name.
But in the class don't name it MyNodeNamePartial name it MyNodeName like this:
This is the same name as the TT file. (MyNodeName) which creates it's own partial class. But now notice we have a value named MODEL of this class type..
The model class holds the ClassName and NameSpaceName and anything else you want to "inject" into the template.
The key to this working as shown,
is that the Runtime Text Template was used! If you use a Text Template, no matter what you do, you will see errors similar to "Model not found" or other ambiguous issues.
Debugging Tips:
"The Model cannot be found" is the T4 generation code telling you that in your partial class with the variable named MODEL, that it cannot find it! Check both your partial and the model types to ensure they are in same namespace as the any other normal class namespace would be if created in that folder.
请参阅 MSDN 参考(“在构造函数中传递参数”部分)。
总结一下:
创建一个与 TT 文件同名的分部类。
然后只需在类的构造函数中传递参数即可
Look at MSDN Reference (Section "Passing parameters in the constructor").
To summarize:
Create a partial class with the same name of your TT File.
Then simply pass your parameters in the constructor of the class
我尝试了这里的所有答案以使其发挥作用,但没有一个适合我的场景。最终我将以下内容添加到我的模板中......
然后它就起作用了
I tried all the answers here to get it to work and none worked for my scenario. Eventually I added the following to my template ...
.. and then it worked