一起谈.NET技术,创建代码生成器可以很简单:如何通过T4模板生成代码?[下篇]

  在《上篇》中我们通过T4模板为我们指定的数据表成功生成了我们需要的用于添加、修改和删除操作的存储过程。但是这是一种基于单个文件的解决方案,即我们必须为每一个生成的存储过程建立一个模板。如果我们提供一种基于多文件的代码生成方式,将会为编程人员带来极大的便利。借助于T4 ToolBox这个开源工具箱,多文件的SQL Generator的实现变得异常简单。

  一、多文件代码生成器会带来多大的便利?

  我们先来直观的感受一下较之《上篇》提供的单一文件的代码生成器,基于多文件的代码生成解决方案会为开发人员带来多大的便利。 同样对于《上篇》创建的数据表T_PRODUCT,之前我们为了生成三个不同的存储过程,我们不得已需要创建3个不同的T4模板文件。实际上我们更需要的方式只需要创建一个T4模板,让我们的SQL Generator自动为我们生成3个包含相应存储过程的.sql附属文件,如左图所示(点击看大图)。

  有的时候,基于单个数据表的存储过程生成方式我们依然觉得不方便。如果我们能够在T4模板文件中指定的数据表的列表,让我们的SQL Generator为列表的每一个数据表都生成CUD三个存储过程,这样的方式更加具有吸引力。如右图所示(点击看大图),一个订单模块包含两个具有主子关系的两张表(T_ORDER和T_ORDER_DETAIL),现在我们在一个T4模板中指定这两个表明,通过SQL Generator可以帮助我们生成6个包含存储过程的.sql附属文件。

  甚至有的时候我们连数据表列表都无需指定,让SQL Generator为所有的表都生成相应的存储过程。我的例子中没有提供这样的功能,但是实现自来不会存在任何问题。

  二、创建自定义的Generator

  在《上篇》中我创建了一个抽象的ProcedureTemplate类,以及三个基于生成CUD存储过程的具体ProcedureTemplate: InsertProcedureTemplate、UpdateProcedureTemplate和DeleteProcedureTemplate。它们都将直接服务于我们今天将要提供的基于多文件的SQL Generator。

  在《上篇》中,这四个Template分别定义在4个不同的TT文件中,3个具体的ProcedureTemplate通过<#@include>指令将抽象ProcedureTemplate模板文件包含过来。由于我们将要创建的T4模板将会使用到这四个类,如果我们用四个<#@include>指令将四个TT文件包含过来,由于T4引擎将会导致对ProcedureTemplate的4次包含,最好将会导致变异问题。个人觉得这应该算是T4引擎解析包含关系的一个局限性,为了解决这个问题我们不得不抽象的ProcedureTemplate和三个具体的ProcedureTemplate都合并成一个TT文件。

  T4 ToolBox为类库中为了提供了一个抽象的T4Toolbox.Generator类用于实现多文件的代码生成。为此我们创建一个TT模板文件,定义了如下一个继承自该类的ProcedureGenerator。ProcedureGenerator的核心是通过属性Templates定义的类型为IEnumerable<ProcedureTemplate>的ProcedureTemplate列表,这个列表在存储过程中进行初始化。而对于ProcedureGenerator的构造函数,处理定义了一个表示数据库连接字符串的databaseName的参数外,要以数组参数的形式指定了生成的存储过程基于的数据表名的列表。


<#@ import namespace="System.Collections.Generic" #>
<#@ include file="ProcedureTemplate.tt" #>
<#@ include file="T4Toolbox.tt" #>
<#+
public class ProcedureGenerator : Generator
{
public IEnumerable<ProcedureTemplate> Templates{get; private set;}

public ProcedureGenerator(string databaseName, params string[] tableNames)
{
if(null == tableNames || tableNames.Length == 0)
{
throw new ArgumentNullException("tableNames");
}

this.Templates = InitlizeTemplates(databaseName,tableNames);
}

private IEnumerable<ProcedureTemplate> InitlizeTemplates(string databaseName, string[] tableNames)
{
foreach(string tableName in tableNames)
{
yield return new InsertProcedureTemplate(databaseName, tableName);
yield return new UpdateProcedureTemplate(databaseName, tableName);
yield return new DeleteProcedureTemplate(databaseName, tableName);
}
}

protected override void RunCore()
{
foreach(ProcedureTemplate tempalte in this.Templates)
{
tempalte.RenderToFile(tempalte.GetProcedureName() + ".sql");
}
}
}
#>

  真正的存储过程的T-SQL脚本实现在重写的RunCore中。由于具体的文本转化逻辑都定义在了ProcedureTemplate中了,所以在这里我们需要遍历的ProcedureTemplate集合中每一个Template对象,调用RenderToFile方法将相应的存储过程的脚本写入以存储过程命名同名的.sql文件中。

  三、ProcedureGenerator如何被使用?

  我们最后来看看我们创建的ProcedureGenerator最终如何被应用于具体的代码生成。其实很简单,我们只需要创建相应的模板文件,通过<#@include>将定义ProcedureGenerator类的TT文件包含近来,最后以代码语句调用块(<#StatementCode#>)的形式实力化该对象,并调用Run方法即可。在构造函数中指定数据库连接字符串的名称和数据表名的列表。下面是基于但表的T4模板。

<#@ template language="C#" hostSpecific="true" debug="true" #>
<#@ include file="Templates\ProcedureGenerator.tt" #>
<#
   new ProcedureGenerator("TestDb","T_PRODUCT").Run();
#>

  下面是基于多表的T4模板:

<#@ template language="C#" hostSpecific="true" debug="true" #>
<#@ include file="Templates\ProcedureGenerator.tt" #>
<#
   new ProcedureGenerator("TestDb","T_ORDER","T_ORDER_DETAIL").Run();
#>

  当你代码生成工作执行之后,会多出一个与TT文件同名的附属文件,你需要手工删除掉它。

  从数据到代码——通过代码生成机制实现强类型编程[上篇] 

  从数据到代码——通过代码生成机制实现强类型编程[下篇] 

  从数据到代码——基于T4的代码生成方式 

  创建代码生成器可以很简单:如何通过T4模板生成代码?[上篇] 

  创建代码生成器可以很简单:如何通过T4模板生成代码?[下篇]

时间: 2024-09-14 18:49:50

一起谈.NET技术,创建代码生成器可以很简单:如何通过T4模板生成代码?[下篇]的相关文章

创建代码生成器可以很简单:如何通过T4模板生成代码?[上篇]

在<基于T4的代码生成方式>中,我对T4模板的组成结构.语法,以及T4引擎的工作原理进行了大体的介绍,并且编写了一个T4模板实现了如何将一个XML转变成C#代码.为了让由此需求的读者对T4有更深的了解,我们通过T4来做一些更加实际的事情--SQL Generator.在这里,我们可以通过SQL Generator为某个数据表自动生成进行插入.修改和删除的存储过程.[文中源代码从这里下载] 一.代码生成器的最终使用效果 我们首先来看看通过直接适用我们基于T4的SQL生成模板达到的效果.右图(点击

《Git学习指南》——1.3 分支的创建与合并很简单

1.3 分支的创建与合并很简单 对于大多数版本控制系统来说,分支的创建与合并通常会因其特殊性而被认为是高级拓展操作.但由于Git最初就是为了方便那些散落在世界各地的Linux内核开发者而创建的,合并多方努力的结果一直都是其面临的最大挑战之一,所以Git的设计目标之一就是要让分支的创建与合并操作变得尽可能地简单且安全. 在下面的图1.4中,我们向你展示了开发者是如何通过创建分支的方式来进行并行开发的.图中的每一个点都代表了该项目的一个版本(即commit).而由于在Git中,我们只能对整个项目进行

一起谈.NET技术,NHibernate 变的简单

下载示例程序代码 - 1,162.6 KB 前言 这篇文章出自于我尝试学习使用Nhiberbnate的挫败感.我发现好像Nhibernate全部的介绍材料不是很模糊就是太详细.我所需要的就是一个简单直接的教程,能让我尽快对NHibernate熟悉起来.我从来没有找到.幸运的是,这篇文章将会满足别人的这些需求. 这篇文章有些长,但是我鼓励你以你的方式来阅读.NHibernate是一个复杂的程序,是一个绵延曲折的学习过程.这篇文章将为你踏平曲折,从几天或是几周缩短到几个小时. 问题 NHiberna

一起谈.NET技术,IoC+AOP的简单实现

对EnterLib有所了解的人应该知道,其中有一个名叫Policy Injection的AOP框架:而整个EnterLib完全建立在另一个叫作Unity的底层框架之上,我们可以将Unity看成是一个IoC的框架.对于一个企业应用来说说,AOP和IoC是我们进行逻辑分离和降低耦合度最主要的方式,而将两者结合起来具有重要的现实意义. 一.基于IoC+AOP的编程 到底将IoC和AOP进行整合后,会对编程但来怎样的影响,我写了一个简单的例子(你可以从这里下载该实例).假设我现在有两个模块,分别称为Fo

一起谈.NET技术,ASP.NET的地址重写(URLRewriter)实现原理及代码示例

一.概述 访问者输入:http://wu-jian.cnbolgs.com/default.aspx,实际请求和响应的地址却是:http://www.cnblogs.com/wu-jian/default.aspx, 这就是UrlRewrite,除了实现二级域名功能,它在简化用户输入地址.SEO.网站版本迭代更新等多个方面发挥着重要作用. 微软曾在.net framework 1.1中提供过一个名为URLRewriter的小工具供开发人员轻松实现UrlRewrite,下载地址为:http://d

一起谈.NET技术,Visual Studio 2010中敏捷开发流程模板的应用

本文将会为您讲述如何使用TFS 2010 MSF Agile 5.0流程模板为迭代项目而提供的工作簿.首先,让我们看一看Visual Studio 2010 IDE中的Team Explorer插件: 接下来,我们将会进入到SharePoint project portal中,为大家展示Team Explorer是如何模拟它的结构的.我们首先右击名字是Team Project的标题的那个节点,如下图所示: 这会让我们进入到SharePoint project portal中,如下图所示.注意Te

新人小白求助 很简单的一个修改密码的代码,但密码一直修改不成功,求大神帮帮忙

问题描述 这是我的修改密码的代码,要求输入用户名,密码,原密码和确认密码四个内容usingSystem;usingSystem.Linq;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebC

一个很简单的无限分类树实现代码_导航菜单

国务院 省级办公单位 安徽 河南省 阜阳市 界首市 河北省 广东省 省级办公单位2 范冰冰2 范冰冰4 某导演 某导演 某导演 某导演 某导演 某导演 某导演 某导演 某导演 某导演 某导演 某导演 某导演 某导演 范冰冰2 范冰冰2 省级办公单位3 省级办公单位4 国务院 省级办公单位 安徽 河南省 阜阳市 界首市 河北省 广东省

一起谈.NET技术,解决T4模板的程序集引用的五种方案

在众多.NET应用下的代码生成方案中,比如CodeDOM,BuildProvider, 我觉得T4是最好的一种.关于T4的基本概念和模板结果,可以参考我的文章<基于T4的代码生成方式>.如果要了解T4具体的应用,则可以参考我的文章<创建代码生成器可以很简单:如何通过T4模板生成代码?>(上篇)(下篇).如果你编写T4模板,你不得不面对一个问题--如何引用一个程序集?VS 2010采用了与VS2008不同的程序集引用的解析机制.本篇文章为你介绍在VS2010下5种不同的程序集引用的方