阿不

潜水

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  212 随笔 :: 0 文章 :: 3078 评论 :: 107万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

T4模板Visual Studio IDE的应用越来越多,现在在VS中,只要与代码生成相关的场景,我们都可以通过修改 T4模板来自定义生成格式,比如MVC的视图模板,Entity Framwork的DataContext模板等等。同时我们还可以自己创建T4模板文件(.tt),使用C#(VB)语法来编写T4模板,它的语法与ASP.NET的语法非常类似,大大降低了.NET程序员的学习成本,关于T4的模板的更多细节请阅读Oleg Sych关于T4的博客文章。

T4模板,除了静态执行输出之外,我们还可以通过程序动态执行并输出。关于动态执行T4模板,可以参考用程序执行 t4 文件Walkthrough: Creating a Custom Text Template Host,这两篇文章。

这两篇文章都讲到,我们要动态执行T4模板,需要自己定义一个ITextTemplatingEngineHost实现类,并在执行时,将它传给T4引擎:

很简单,我们就可以动态执行T4模板。但是,如何传递参数给模板的运行时?以上的介绍中并没有提及,变量是模板引擎的血液,而以上的两篇文章刚好都没有介绍到如何传递变量给T4引擎上下文。花了几个小时,终于在这篇博文中找到一点线索,博文中介绍的是T4中,parameter这个声明的作用和运行原理,它也直接告诉我如何去在运行时传递参数给T4引擎上下文。简单的总结一下:我们可以通过两种方式经T4模板传递上下文,分别是通过CallContext和ITextTemplatingSession对象。通过CallContext传递对象要特别注意的是,当前宿主程序的执行上下文和T4模板引擎上下文是不同的,我们可以通过CallContext.LogicalSetData这个方法来将本地对象传递到另一个上下文使用。另一种办法就是通过传递Session对象的方式,这个Session的概念跟ASP.NET的Session概念很相似,它是一个IDictionary<string,object>对象,它允许我们可以定义一些全局变量,供T4引擎上下文使用。那么,同样的问题是,在宿主上下文中,我们如何将Session传递到T4上下文呢?看这段代码:

也就是在标准的Host对象实现中,除了实现ITextTemplatingEngineHost,还需实现ITextTemplatingSessionHost这个接口,这个接口就会带有一个Session属性的定义。我们就可以通过给这个Session赋值来达到参数传递的目的。这个设想,我们也可以在Engine的内部代码中得到验证:

InitializeSessionWithHostData用于初始化Engine使用的Session数据,它会去检查我们传入的host对象是否实现了ITextTemplatingSessionHost,如有实现,则会将我们传入的Session带到内部去使用。在弄清原理后,我们就可以在Walkthrough: Creating a Custom Text Template Host介绍的自定义ITextTemplatingEngineHost实现类上,再添加实现ITextTemplatingSessionHost接口,然后在执行T4模板时,将需要的参数以Session的方式传给T4引擎使用:

以上的实现是通过把参数值放在Session中传递到T4模板上下文中。同时我们也可以CallContext的方式来传递参数:

但是不管怎么样,是通过Session还是CallContext,我们的Host实例都是要实现ITextTemplatingSessionHost接口,并且为初始化Session属性。否则在调用this.Session.ContainsKey时就会出现空引用异常,因为它会优先去检查Session中是否有需要的参数值。

另外还有其它的办法,我们也可以达到类似的目的。比如:我们也可以定义自己的“声明”标识,然后通过自己解析这些”声明”,动态生成一些对象实例提供给T4模板使用,但是这种方法更为复杂,需要涉及动态对象生成和代码生成等技术。如有兴趣可参考:Walkthrough: Creating a Custom Directive Processor

最后附上例子

posted on   阿不  阅读(7613)  评论(15编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示