T4即为Text Template Transformation Toolkit,一种可以由自己去自定义规则的代码生成器。根据业务模型可生成任何形式的文本文件或供程序调用的字符串

在VS中T4模板是没有智能提示和颜色标注的,可以安装官方推荐插件:tangibleT4EditorPlusModellingTools

9.1 T4 文本模板有两种类型

  • 设计时模版

可在应用程序中执行运行时 T4 文本模板("预处理过的"模板)以便生成文本字符串(通常作为其输出的一部分)。

  若要创建运行时模板,请向您的项目中添加"已预处理的文本模板"文件。 另外,您还可以添加纯文本文件并将其"自定义工具"属性设置为"TextTemplatingFilePreprocessor"。

  • 运行时模版

在 Visual Studio 中执行设计时 T4 文本模板,以便定义应用程序的部分源代码和其他资源。

  通常,您可以使用读取单个输入文件或数据库中的数据的多个模板,并生成一些 .cs、.vb 或其他源文件。 每个模板都生成一个文件。

  若要创建设计时模板,请向您的项目中添加"文本模板"文件。 另外,您还可以添加纯文本文件并将其"自定义工具"属性设置为"TextTemplatingFileGenerator"。

9.2 文本模板的组成

9.2.1 指令

  • 模版指令

<#@ template debug="false" hostspecific="false" language="C#" #>

模板指令中所有特性均为可选的。其中需要说明的是 hostspecific ,如果将此特性设为true,则会将名为Host的属性添加到由文本模板生成的类中。该属性是对象转换引擎的宿主的引用,并声明为Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost 类型。

  • 参数指令

<#@ parameter type="Full.TypeName" name="ParameterName" #>

顾名思义,就是用来传参的,出现在运行时模板中。

  • 输出指令

<#@ output extension=".fileNameExtension" [encoding="encoding"] #>

用于设置输出文件的后缀名和文件编码。

extension:输出文件扩展名,默认为".cs"

encoding:文件编码,默值为utf-8

  • 程序集指令

<#@ assembly name="System.Core" #>

程序集指令相当于VS里面我们添加程序集引用的功能。T4模版的程序集引用是完全独立的。

可以使用 $(variableName) 语法引用 Visual Studio的变量。几个常用的变量如下:

  • $(SolutionDir):当前项目所在解决方案目录
  • $(ProjectDir):当前项目所在目录
  • $(TargetPath):当前项目编译输出文件绝对路径
  • $(TargetDir):当前项目编译输出目录,即web项目的Bin目录
  • 导入指令

<#@ import namespace="namespace" #>

import 指令允许您在不提供完全限定名称的情况下引用另一个命名空间中的元素。 它等效于 C# 中的 using。

  • 包含指令

<#@ include file="filePath" #>

包含指令可以提高代码复用率,比如我们可以将一些常用的程序集、命名空间引用放到一个文件里,使用时仅需要引用下即可,省去了每次都要重新引用一遍的烦恼

  • 文本块

    文本块直接向输出文件插入文本。 文本块没有特殊格式。 例如,下面的文本模板将生成一个包含单词"Hello World!"的文本文件:

<#@ output extension=".txt" #>

Hello World!

9.2.2 控制块

控制块是用于转换模板的程序代码节

  • 标准控制块

    标准控制块是生成输出文件部件的程序代码节。

    在模板文件中,可以混合使用任意数量的文本块和标准控制块。 但是,不能在控制块中嵌套控制块。 每个标准控制块都以 <# ... #> 符号分隔。

    例如,如果使用下面的控制块和文本块,则输出文件包含行"0, 1, 2, 3, 4 Hello!":

<#

; i < ; i++)

{

Write(i + ", ");

}

Write("4");

#>

Hello!

也可以交错文本和代码,而不必使用显式 Write() 语句。 以下示例输出"Hello!"四次:

<#

for(int i = 0; i < 4; i++)

{

#>

Hello!

<#

}

#>

在代码中,可以使用 Write()语句的位置都可以插入文本块。

  • 表达式控制块

    表达式控制块计算表达式并将其转换为字符串。 该字符串将插入到输出文件中。

    表达式控制块以 <#= ... #> 符号分隔。

    例如,如果使用下面的控制块,则输出文件包含"5":

<#= + #>

  • 类功能控制块

    类功能控制块定义属性、方法或不应包含在主转换中的所有其他代码。 类功能块常用于编写帮助器函数。 通常,类功能块位于单独的文件中,这样它们可以包含在多个文本模板中。

    类功能控制块以 <#+ ... #> 符号分隔,可以简单的认为<#+ ...#>定义的内容为我们的类文件

    例如,下面的模板文件声明并使用一个方法:

<#@ output extension=".txt" #>

Squares:

<#

for(int i = 0; i < 4; i++)

{

#>

The square of <#= i #> is <#= Square(i+1) #>.

<#

}

#>

That is the end of the list.

<#+ // 定义方法

private int Square(int i)

{

return i*i;

}

#>

9.3 案例:创建模型

可以借助 DbHelper.ttinclude 和 Manager.ttinclude 两个第三方资源提高T4模板的开发效率。

DbHelper.ttinclude 的主要方法:

DbHelper.GetDbTables() :获取指定数据库的所有表。

DbHelper.GetDbColumns():获取指定表的所有列。

Manager.ttinclude 的主要方法:

Create(): 获取该类的一个实例。

StartNewFile():新建一个文件。

Process(true):生成文件。

另外,数据库的连接字符串在Config类(DbHelper.ttinclude 文件)中。

生成实体类T4模板的代码如下:

<#@ template debug="false" hostspecific="true" language="C#" #>

<#@ assembly name="System.Core" #>

<#@ assembly name="System.Data.dll" #>

<#@ assembly name="System.Data.DataSetExtensions.dll" #>

<#@ import namespace="System.Data" #>

<#@ import namespace="System.Data.SqlClient" #>

<#@ import namespace="System.Linq" #>

<#@ import namespace="System.Text" #>

<#@ import namespace="System.Collections.Generic" #>

<#@ output extension=".cs" #>

<#@ include file="../Common/CodeTemplates/DbHelper.ttinclude"#>

<#@ include file="../Common/CodeTemplates/Manager.ttinclude"#>

<#

var manager = Manager.Create(Host, GenerationEnvironment);

var tables=DbHelper.GetDbTables(Config.ConnectionString,Config.DbDatabase);

foreach (DbTable table in tables)

{

manager.StartNewFile(table.TableName+".cs");

#>

using System;

namespace Model

{

public class <#=table.TableName#>

{

<#

foreach(var col in DbHelper.GetDbColumns(Config.ConnectionString,Config.DbDatabase,table.TableName))

{

#>

public <#=col.CSharpType#><# if(col.CommonType.IsValueType && col.IsNullable){#>?<#}#> <#=col.ColumnName#> { get; set; }

<#

}

#>

}

}

<#

}

manager.Process(true);

#>

Asp.net MVC企业级开发(09)---T4模板的更多相关文章

  1. Asp.net MVC企业级开发(01)---Autofac

    1.1 控制反转 在面向对象设计的软件系统中,它的底层都是由N个对象构成的,各个对象之间通过相互合作,最终实现系统的业务逻辑.同时,对象之间的耦合关系是无法避免的,也是必要的,这是协同工作的基础.但是 ...

  2. Asp.net MVC企业级开发(04)---SignalR消息推送

    Asp.net SignalR是微软为实现实时通信而开发的一个类库.可以适用于以下场景: 聊天室,如在线客服系统,IM系统等 股票价格实时更新 消息的推送服务 游戏中人物位置的实时推送 SignalR ...

  3. Asp.net MVC企业级开发(02)---Log4net

    Log4Net 是用来记录日志的,可以将程序运行过程中的信息输出到一些地方(文件.数据库.EventLog等).日志就是程序的“黑匣子”,可以通过日志查看系统的运行过程,从而发现系统的问题. 日志的作 ...

  4. vs 2013下自定义ASP.net MVC 5/Web API 2 模板(T4 视图模板/控制器模板)

    vs 2013下自定义ASP.net MVC 5/Web API 2  模板(T4 视图模板/控制器模板): Customizing ASP.NET MVC 5/Web API 2 Scaffoldi ...

  5. ASP.NET MVC企业级项目框架

    ASP.NET MVC企业级项目框架 MVC项目搭建笔记---- 项目框架采用ASP.NET MVC+Entity Framwork+Spring.Net等技术搭建,搭建过程内容比较多,结合了抽象工厂 ...

  6. Asp.net Mvc模块化开发之分区扩展框架

    对于一个企业级项目开发,模块化是非常重要的. 默认Mvc框架的AreaRegistration对模块化开发真的支持很好吗?真的有很多复杂系统在使用默认的分区开发的吗?我相信大部分asp.net的技术团 ...

  7. 像asp.net Mvc一样开发nodejs+express Mvc站点

    像asp.net Mvc一样开发nodejs+express Mvc站点 首先,我是个c#码农.从事Mvc开发已然4个年头了,这两年前端MVC的兴起,我也跟风学了一些,对前端的框架也了解一些,angu ...

  8. 关于《ASP.NET MVC企业级实战》

    大家好,我的书<ASP.NET MVC企业级实战>已经出版啦,感谢大家过去的关注与支持!前言部分,出版的时候漏了部分内容,我这里将其贴出来. 本书提供源码和教学PPT课件!(源码在书中第3 ...

  9. Asp.net Mvc模块化开发系列(目录)

    模块化开发是非常重要的,模块化开发是个系统性问题,为此我觉得有必须要写一个系列的文章才能基本说的清楚 那又为什么要写一个目录呢? 其一.是对我昨天承诺写一个系列新的文章的回应 其二.是先写出一个大纲, ...

随机推荐

  1. 使用 Docker Alpine 镜像安装 nginx

    微镜像Alpine,Alpine Linux 是一款独立的⾮商业性的通⽤ Linux 发行版,Alpine Linux 围绕 musl libc 和 busybox 构建,尽管体积很小,Apline ...

  2. jenkins使用小技巧:jenkins构建出来的war/jar包如何带上SVN号?

    在实际使用过程中,一般会这样比如说打出来的包是 mypackage.jar, 但是每次打出来都是固定的 mypackage.jar如何来区分和上一个包的区别呢? 一般来说,会把打出来的包带上个 svn ...

  3. LOJ 510: 「LibreOJ NOI Round #1」北校门外的回忆

    题目传送门:LOJ #510. 题意简述: 给出一个在 \(K\) 进制下的树状数组,但是它的实现有问题. 形式化地说,令 \(\mathrm{lowbit}(x)\) 为在 \(K\) 进制下的 \ ...

  4. 登录-退出,在T分钟实现BC次用户登录退出,单次登录-退出%90用户时间t,需要的并发用户(线程)

    聚合报告%90响应时间:%90用户响应时小于该值 2种理解方式: 一. 1s可完成的用户1/t: T分钟完成的用户T *(1/t); BC次用户需要的线程数Thread= BC/(T*(1/t)) = ...

  5. LG1155 「NOIP2008」双栈排序 二分图判定

    问题描述 LG1155 题解 \(i,j\)如果不能进入一个栈,要满足存在\(k\),使得\(i<j<k\)且\(a_k<a_i<a_j\) 如果\(i,j\)不能进入一个栈, ...

  6. cf1039D 分块

    cf1039D 链接 cf 思路 一次k可以贪心O(n)算. 对于\(≤\sqrt{n}\)的k,暴力算. 对于\(>\sqrt{n}\)的k,最多会有\(\sqrt{n}\)种答案,而且答案单 ...

  7. Appium入门指南 - 环境搭建和Case编写

    本文档将详细介绍如何搭建 Appium 的运行环境,以及如何编写一个简单的 UI 自动化测试用例.其中,也会穿插讲解一些 Appium 的基本知识.关于 Appium 的更多信息,大家可以查看官方文档 ...

  8. [LeetCode] 2. Add Two Numbers 两个数字相加

    You are given two non-empty linked lists representing two non-negative integers. The digits are stor ...

  9. KMP 串的模式匹配 (25分)

    给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出.如果找不到,则输出“Not ...

  10. it's over | 2019 CSP-S 第二轮认证(超长预警)

    也许应该从Day -1(2019年11月14日周四)开始说起? 卑微的我们在学长的怂恿下终于...停课了(哇我们太菜了,只停一天半的课有个卵用 早读后我带头去办公室请假,飞哥很大方地答应了,同时免了我 ...