Text Template Transformation Toolkit

      1.且算简介
 
      笔者以一个英文字母和一个数字取了一个简单的名字。名唤"T4"(名字太短,不易点,体验不好,已修改)。
      也许你会好奇,想着T4何也?然后轻击鼠标,点开。亦或您知道,只是想看看,您或轻或重的点击鼠标,打开。
      笔者这里写的T4是指“T4文本模板”。它是微软自家产的。一个基于模板的代码生成器。它由文本块和控制逻辑块组成的一个模板,可以自动的生成一些文本。有点类似于动软或者Code Smith,只是笔者认为它可比动软或者Code Smith优秀些。,毕竟它是微软自己家的。
      那也许您也会问,为什么叫“T4”也不是“T3”或者“M2”什么的呢?
      这是因为它的因为全称是Text Template Transformation Toolkit。它的全称的四个单词的首字母全部是以T开头的,故尔得此名。
      那么用它有什么好处呢?
      它可以快速的为我们生成一些代码,节省我们的时间。加快开发效率。比如笔者曾经写过一篇博文,讲的是不写代码只要点几点就可以生成一个实体类的CRUD(此文受到了争议,笔者当时只是想做到的是,如若你不知道可以这样,那么你看到了我这样了,那么你也许会感点兴趣,然后仔细研究一下里面的详细代码什么的,此是初衷,不再解释),那么这里面的控制器的代码和视图的代码,勿庸置疑,亦是用到了T4模板。或者我们用EF映射了一个实体的时候,那么此实体的edmx的下面也是有一个由tt结尾的文件也是T4模板,我们如若开始学的时候也可以看一下这个里面的代码,正如我的那篇点点点。
 
 
 
 
 
      2.且举个好吃(简单易懂)的栗子
 
      我们新建一个控制台的项目。然后在此项目上加一个文本模板的选项,名叫“TestTemplateDemo”。如图:
 
      那么会生成这样的一个文件,里面已有的代码如下:
      此原本已有的代码可以认为是指令块。比如程序集指令,导入指令,输入指令(至于哪一行属于什么指令,读者自己判断)。
      另外T4模板还可以有文本块和控制块。文本块,可以认为是1+1=2,很简单,也就是使输入指令为.txt,然后再下面输入一个纯的文本也就是了(笔者是这么认为的,不知对否)。
     控制块就是我们在项目中会用到的,也就是里面写一些语言,比如C#,最后C#的代码会运行输出(依旧笔者个人理解,官方解释就不找了,官方写的都比较难懂)。
 
  1. <#@ template debug="false" hostspecific="false" language="C#" #>
  2. <#@ assembly name="System.Core" #>
  3. <#@ import namespace="System.Linq" #>
  4. <#@ import namespace="System.Text" #>
  5. <#@ import namespace="System.Collections.Generic" #>
  6. <#@ output extension=".cs" #>
  7.  
  8. public class Samsung
  9. {
  10. <# for(int i=;i<;i++) {#>
  11. public string S<#=i#>{get;set;}
  12. <#}#>
  13. }

写一下控制块的代码

我们CTRL+S一下,打开tt下面的cs文件,看一下我们的三星旗舰:
  1. public class Samsung
  2. {
  3. public string S1{ get; set;}
  4. public string S2{ get; set;}
  5. public string S3{ get; set;}
  6. public string S4{ get; set;}
  7. }

看一下三星的旗舰

    是的,三星万年不变大塑料机是由T4模板自动帮我们生成的。其模板内代码写法不解释,跟MVC的ASPX引擎没什么两样。
    好吧,笔者真心不太喜欢三星的大塑料,要不换成魅族的梦想可好。嗯,好吧,就当检测一下T4模板也是好的。

  1. <#@ template debug="false" hostspecific="false" language="C#" #>
  2. <#@ assembly name="System.Core" #>
  3. <#@ import namespace="System.Linq" #>
  4. <#@ import namespace="System.Text" #>
  5. <#@ import namespace="System.Collections.Generic" #>
  6. <#@ output extension=".cs" #>
  7.  
  8. public class Meizu
  9. {
  10. <# for(int i=;i<;i++) {#>
  11. public string MX<#=i#>{get;set;}
  12. <#}#>
  13. }

修改下控制块代码,我想要梦想

CTRL+S,看一下梦想之作:
  1. public class Meizu
  2. {
  3. public string MX1{ get; set;}
  4. public string MX2{ get; set;}
  5. public string MX3{ get; set;}
  6. public string MX4{ get; set;}
  7. }

且容我看一眼梦想。

那么T4是有点帅,还是很有点帅。

那么很有点帅,或者相当帅吧。

 
 
 
 
       3.且再举一个栗子(来自实际项目)
 
       此"栗子",可能是比上面略复杂一点,来源于实际项目中,相信仔细咀嚼味道还是鲜美的。
       我一个项目中有数据访问接口层,访问接口层(IBaseDal)要用来约束访问,比如约定了其类型是一个泛型T类型的且其有一个默认的构造函数。一个实现了IBaseDal接口的IUserDal。访问层(BaseDal)主要用来封装一些实体的公共方法,其实现IBaseDal。下面还有实现和继承了访问层以及实现了数据接口层的UserDal。其关系可见下面代码。至于UML类图,感兴趣的朋友可以自己画一下,本是打处用笔在纸上画好然后,然后拍照示意之。不过笔者手机出问题了,也不想用其他方式弄了,此处也就省略了。
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace Anmutu.OA.IDAL
  8. {
  9. /// <summary>
  10. /// 此接口抽象了DAL实例里公共方法的约束。
  11. /// </summary>
  12. public interface IBaseDal<T> where T: class, new ()
  13. {
  14. T Add(T entity);
  15. bool Update(T entity);
  16. bool Delete(T entity);
  17. int Delete( params int[] ids);
  18. }
  19. }

IBaseDal

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Anmutu.OA.Model;
  8.  
  9. namespace Anmutu.OA.IDAL
  10. {
  11. /// <summary>
  12. /// 创建一个接口,约定其返回类型是User类,参数是一个user实体。
  13. /// </summary>
  14. public interface IUserDal:IBaseDal<User>
  15. {
  16.  
  17. }
  18. }

IUserDal

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using Anmutu.OA.Model;
  9. using EntityState = System.Data.Entity.EntityState;
  10.  
  11. namespace Anmutu.OA.DAL
  12. {
  13. /// <summary>
  14. /// 把数据库访问层的公共方法抽出来实现。
  15. /// </summary>
  16. /// <typeparam name="T"></typeparam>
  17. public particl class BaseDal<T> where T: class, new() //类。且有一个默认的构造函数。
  18. {
  19. //写在这里就没做到线程实例唯一了。此处亦就用简单工厂得到上下文实例。
  20. private Model.AnmutuModelContainer db = new AnmutuModelContainer();
  21. public T Add(T entity)
  22. {
  23. db.Set<T>().Add(entity);
  24. db.SaveChanges();
  25. return entity;
  26. }
  27.  
  28. public bool Update(T entity)
  29. {
  30. db.Entry(entity).State = EntityState.Modified;
  31. return db.SaveChanges() > ;
  32. }
  33.  
  34. public bool Delete(T entity)
  35. {
  36. db.Entry(entity).State = EntityState.Deleted;
  37. return db.SaveChanges() > ;
  38. }
  39.  
  40. public int Delete( params int[] ids)
  41. {
  42. foreach ( var id in ids)
  43. {
  44. //如若实体已经在内存中就在内存中拿,如果内存中没有则查询数据库。
  45. var entity = db.Set<T>().Find(id);
  46. db.Set<T>().Remove(entity);
  47. }
  48. return db.SaveChanges();
  49. }
  50. }
  51. }

BaseDal

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Anmutu.OA.IDAL;
  8. using Anmutu.OA.Model;
  9. using EntityState = System.Data.Entity.EntityState;
  10.  
  11. namespace Anmutu.OA.DAL
  12. {
  13. public partial class UserDal : BaseDal<User>,IUserDal //这里实现接口。
  14. {
  15.  
  16. }
  17. }

UserDal

笔者注:其中有代码少了PARTICAL关键字,如若改兴趣,你会发现是哪里的,笔者就不回去做修改了。

      我们很显然的就可以看出来。如若我们要再加一个Role实体的话,它理应有这些公共的方法。而按照此数据访问层的写法的话,我们可能就得写很多类似的代码了。很多地方相应的User改变成Role,也就可以了。那么T4隆重出场了(笔者在这里写了四个,是为表示很多地方都可以用到T4,示例只写一个)。

  1. <#@ template language="C#" debug="false" hostspecific="true"#>
  2. <#@ include file="EF.Utility.CS.ttinclude"#>
  3. <#@ output extension=".cs"#>
  4.  
  5. <#
  6. CodeGenerationTools code = new CodeGenerationTools(this);
  7. MetadataLoader loader = new MetadataLoader(this);
  8. CodeRegion region = new CodeRegion(this, );
  9. MetadataTools ef = new MetadataTools(this);
  10.  
  11. string inputFile = @"..\\Anmutu.OA.Model\\AumutuModel.edmx";
  12. EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
  13. string namespaceName = code.VsNamespaceSuggestion();
  14. EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
  15. #>
  16.  
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Data;
  20. using System.Linq;
  21. using System.Text;
  22. using System.Threading.Tasks;
  23. using Anmutu.OA.IDAL;
  24. using Anmutu.OA.Model;
  25. using EntityState = System.Data.Entity.EntityState;
  26.  
  27. namespace Anmutu.OA.DAL
  28. {
  29. <#
  30. foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
  31. {
  32. #>
  33. public partial class <#=entity.Name#>Dal : I<#=entity.Name#>Dal
  34. {
  35.  
  36. }
  37. <#}#>
  38. }

IUserDal的T4

      那么,这样当你有实体且已保存的时候,你只需要在此处CTRL+S一下,数据访问接口层(IBaseDal与IUserDal)的代码也就自动为你生成好了。至于在上面这四个地方的其他地方,同样可以采用到T4模板自动相应生成。当然一个比较好的框架的话,不仅DAL层会有相应的可以通过T4就可以相应生成代码的。BLL层或者UI层也是可以有的,或者是各种层中的工厂。我们都可以相对应的写T4。然后,我们保存就会自动为我们生成相应的代码了。生成后,自然会有各自对象,我们就可以直接拿来用了。
      只是当我新增一个实体后且已保存了。且算DAL层有4个T4,BLL层也有4个T4,那我都得打开一遍,然后CTRL+S,才会为我们生成相应的代码,这样也慢了一点。
      至于这个嘛,你可以点击VS上“生成(BUILD)”中会有一个“转换所有T4模板(Transform All T4 Templates)”。VS则会自动的帮你重新保存一下所有的T4,也自然会自动帮我们生成各种层之间的各个T4,不用我们打开每个去保存。那么,现在假设你新增一个实体已保存且每个层中的T4模板均已写好。你想快速的去操作这个实体,那么,你做的只是需要点两下就可以去操作此实体了。那些DAL层中的IDAL或者DAL,BLL层的IBLL或者BLL,亦或是各种工厂,那些代码,根本就不需要你写。所以,由此看T4是可以帮助我们提高开发效率的。
       如此看来上面的那个“栗子”算不得相当帅,这个倒时可以算的。
       笔者初探T4,如若有不对之处,还请斧正。谢。
 
 

Text Template Transformation Toolkit的更多相关文章

  1. C# Meta Programming - Let Your Code Generate Code - Introduction of The Text Template Transformation Toolkit(T4)

    <#@ template language="C#" #> <#@ output extension=".cs" #> <#@ a ...

  2. T4((Text Template Transformation Toolkit))模版引擎之基础入门 C#中文本模板(.tt)的应用

    1 关于C#中文本模板(.tt)的简单应用https://blog.csdn.net/zunguitiancheng/article/details/78011145 任何一个傻瓜都能写出计算机能理解 ...

  3. go语言的模板,text/template包

    go语言的模板,text/template包 定义 模板就是将一组文本嵌入另一组文本里 传入string--最简单的替换 package main import ( "os" &q ...

  4. script "text/template"

    <script type="text/template" id="orgItem"> <div class="{orgClass}& ...

  5. go标准库的学习-text/template

    参考:https://studygolang.com/pkgdoc 导入方式: import "text/template" template包实现了数据驱动的用于生成文本输出的模 ...

  6. <script type="text/template">是干什么的,为什么要把html写在js中? 这是什么编程语言风格,都能这样用吗?

    这一段存放了一个模板.在js里面,经常需要使用js往页面中插入html内容.比如这样: var number = 123; $('#d').append('<div class="t& ...

  7. 前端模板<script type="text/template" id="tmpl">

    前端模板, 比连接字符串好用多了, 还可以使用循环\判断等语句, 减少工作量 <script type="text/template" id="member-tmp ...

  8. 关于MVC模板渲染的一点小事type="text/template"

    先上一个demo,简单粗暴,请自便 <!DOCTYPE html> <html> <head lang="en"> <meta chars ...

  9. 关于 <script type='text/template' > 的妙用 / 使用jquery获取iframe加载完成事件

    https://www.cnblogs.com/ddqyc/p/6200539.html <!DOCTYPE html> <html> <head> <met ...

随机推荐

  1. External Table

    CREATE TABLE AS SELECT,使用Oracle9i的External Table  Oracle 9i 的一项新特性就是 External Table,它就象通常的数据库表一样,拥有字 ...

  2. DIV+CSS解决IE6,IE7,IE8,FF兼容问题

    1.IE8下兼容问题,这个最好处理,转化成IE7兼容就可以.在头部加如下一段代码,然后只要在IE7下兼容了,IE8下面也就兼容了:1. <metahttp-equivmetahttp-equiv ...

  3. 小菜鸟带着梦想学chromium

    风雨送春归, 飞雪迎春到. 已是悬崖百丈冰, 犹有花枝俏. 俏也不争春, 只把春来报. 待到山花烂漫时, 她在丛中笑. 这首卜算子·咏梅可是应了我的心情了.最近换工作,受到频频打击,面试过程中发现满世 ...

  4. 【学习笔记】【C语言】字符串数组

    1.使用场合 * 一维字符数组中存放一个字符串,比如一个名字char name[20] = "mj" * 如果要存储多个字符串,比如一个班所有学生的名字,则需要二维字符数组,cha ...

  5. 多文件上传artDialog+plupload

    一.效果展示 包括文件上传面板以及文件上传列表 二.介绍 长话短说,采用spring springMVC mybatis maven mysql,实现多文件上传功能,下载使用的是流的形式. 其中涉及的 ...

  6. 杭电ACM1170--Balloon Comes!

    地址  http://acm.hdu.edu.cn/showproblem.php?pid=1170 #include<stdio.h> int main() { int t,a,b; ] ...

  7. VBA访问SQLSERVER2005筛选数据库

    EXCEL版本2010, 引用 Private Sub CommandButton1_Click() Dim conn As New ADODB.Connection Dim rs As New AD ...

  8. unity打包android游戏部分问题总结

    一:虚拟导航栏挡到游戏按钮: 解决方案如下: 1.获取焦点的时候隐藏 虚拟导航条 Navigation bar 隐藏导航条 2.出现导航条的时候,改变游戏界面大小 Unity tidbits: cha ...

  9. Jquery Slick幻灯片插件

    slick 是一个基于 jQuery 的幻灯片插件,具有以下特点: 支持响应式 浏览器支持 CSS3 时,则使用 CSS3 过度/动画 支持移动设备滑动 支持桌面浏览器鼠标拖动 支持循环 支持左右控制 ...

  10. net中的编译

    1.MSBuild 四个基本块(属性.项.任务.目标): MSBuild属性:   属性是一些键/值对,主要用来存储一些配置信息. MSBuild  项:   主要是存储一些项目文件信息,以及文件的元 ...