CodeSmith模板生成
转:http://blog.csdn.net/jason_ldh/article/details/9887073
一、 工具设置
CodeSmith默认是不支持中文的,那么我们必须要先设置使其支持中文显示,保存。并且要能够在生成文件中支持中文。
- [Tools->Options...->Studio->Editor->Enable unicode]将这个选项勾上,那么CodeSmith就可以显示和保存中文了。
- 在你的模板的最前面的一句话,C#为例:
<%@ CodeTemplate TargetLanguage="Text" Src="" Inherits="" Debug="False" CompilerVersion="v3.5" Description="Template description here." %>
中加入ResponseEncoding="UTF-8" 的标签。将会使得生成的文件也支持中文。
- [Tools->Options...->Studio->Editor->Convert tab to]去掉这个的勾选,就是不使用空格来替换Tab。
二、 模板区域说明
CodeSmith的模板分为六个区域:模板说明区域,属性设置区域,注册模板区域,引用声明区域,模板区域,函数区域。
(一) 模板说明区域,只有一句话:
<%@ CodeTemplate ResponseEncoding="UTF-8" TargetLanguage="Text" Src="" Inherits="" Debug="False" CompilerVersion="v3.5" Description="这里是模板说明" %>
(二) 属性设置区域
你模板需要那些外接参数,都可以写在这里。当然还有一些其他的参数需要些在函数区域,在后面我们再来描述。
1) String类型参数声明:
<%@ Property Default="AAA" Optional="True" Category="输入参数" Description="这是一个字符串型的参数" %>
2) Bool类型参数声明:
<%@ Property Default="True" Optional="False" Category="输入参数" Description="这是一个布朗型的参数" %>
3) DatabaseSchema类型参数声明:
<%@ Property Category="Context" Description="这是一个数据库" %>
4) TableSchemaCollection类型参数声明:
<%@ Property Category="Context" Description="这是一个数据表集合" %>
5) TableSchema类型参数声明:
<%@ Property Category="Context" Description="这是一个数据表" %>
(三) 注册模板区域
在你的模板中可以调用其他的模板用于生成,当然,你调用的模板所需要的参数你都必须给出。注册代码如下:
<%@ Register Template="B.cst" MergeProperties="False" ExcludeProperties="" %>
这就是将B模板注册到A模板中。
(四) 引用声明区域
在这里要将我们使用到了的应用集都在这里写出来,如果使用到数据库就一定要添加下面的两个。
<%@ Assembly %>
<%@ Import Namespace="SchemaExplorer" %>
要自己控制输出文件的话就需要添加:<%@ Import Namespace="System.IO" %>
(五) 模板区域
这里就是我们控制要输出的文件或者界面的内容。
直接输出值为<%= ThisIsString %>
调用代码为<% if (ThisIsBool) { %>A<% } %> 如果ThisIsBool为true则输出A。
(六) 函数区域
在这里我们可以定义我们自己的函数,用于一些复杂的组合、代码的重用等。代码格式和C#完全一样。
三、 模板编写方法
A. 直接输出
在模板区域直接输入文本,就会直接输出的output里面了。
B. 变量输出
例如输出ThisIsString的变量值:<%= ThisIsString %>
再例如输出ThisIsTable的名字:<%=
ThisIsTable.Name %>
C. 调用函数
例如,如果输入的ThisIsBool为true就输出A字符。
<% if (ThisIsBool) { %>A<% } %>
D. 调用模板
这里我们将在A模板内调用并显示B模板。每个模板都有一个Response来存储模板输出的。模板显示是调用Render()方法来完成的。
<% for(int i = 0; i < ThisIsTableList.Count; i++)
{
B b = new B();
b.ThisIsTable = ThisIsTableList[i];
b.Render(this.Response);
} %>
E. 遍历Database或TableCollection内的表
这里我们可以使用for或者foreach做循环,为了通用性例子全部使用for做循环。
遍历ThisIsDatabase并输出表名
<% for (int t = 0; t < ThisIsDatabase.Tables.Count; t++) { %>
<%= ThisIsDatabase.Tables[t].Name %>
<% } %>
F. 遍历Table的列
遍历ThisIsTable的列并且生成类似如下格式的语句:
//数据库类型:DbType.int
private int _ID;
这里调用了一个方法DataType2CSharpType(System.Data.DbType dbType)在后面将会讲到。
<% for (int c = 0; c < ThisIsTable.Columns.Count; c++) { %>
//数据库类型:DbType.<%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %>
private <%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %> _<%= ThisIsTable.Columns[c].Name %>;
<% } %>
输出结果:
//数据库类型:DbType.int
private int _ID;
//数据库类型:DbType.int
private int _ClassID;
//数据库类型:DbType.string
private string _StudentName;
G. 遍历Table的PK
<% for (int c = 0; c < ThisIsTable.PrimaryKey.MemberColumns.Count; c++) { %>
主键<%= c %>:<%= ThisIsTable.PrimaryKey.Name %>
<%= ThisIsTable.PrimaryKey.Table.Name %>.<%= ThisIsTable.PrimaryKey.MemberColumns[c].Name %>
<% } %>
输出结果 :
主键0:PK_Student
Student.ID
H. 遍历Table的FK(Table自己是外键表<即Table为明细表>)
这里说明下,下面的代码仅仅只是对FK里面的列是一对一的有效,如果是多对多的FK需要修改下面的0的地方为循环即可。
<% for (int c = 0; c < ThisIsTable.ForeignKeys.Count; c++) { %>
外键<%= c %>:<%= ThisIsTable.ForeignKeys[c].Name %>
外键<%= c %>对应的列
<% for (int i = 0; i < ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
<%= ThisIsTable.ForeignKeys[c].ForeignKeyTable.Name %>.<%= ThisIsTable.ForeignKeys[c].ForeignKeyMemberColumns[0].Name %> <——来自于 <%= ThisIsTable.ForeignKeys[c].PrimaryKeyTable.Name %>.<%= ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns[0].Name
%>
<% } %>
<% } %>
输出结果:
外键0:FK_Student_Class
外键0对应的列
I. 遍历Table的FK(Table自己是主键表<即Table为父表>)
<% for (int c = 0; c < ThisIsTable.PrimaryKeys.Count; c++) { %>
其他表外键<%= c %>:<%= ThisIsTable.PrimaryKeys[c].Name %>
其他表外键<%= c %>对应的列:
<% for (int i = 0; i < ThisIsTable.PrimaryKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
<%= ThisIsTable.PrimaryKeys[c].PrimaryKeyTable.Name %>.<%= ThisIsTable.PrimaryKeys[c].PrimaryKeyMemberColumns[0].Name %> 作用于——> <%= ThisIsTable.PrimaryKeys[c].ForeignKeyTable.Name %>.<%= ThisIsTable.PrimaryKeys[c].ForeignKeyMemberColumns[0].Name
%>
<% } %>
<% } %>
输出结果:
其他表外键0:FK_ExamScore_Student
其他表外键0对应的列:
Student.ID 作用于——> ExamScore.StudentID
四、 函数区域用法
之前我们提到过,有些参数必须要写在函数区域中。当然这些参数就是需要有一些其他组件支持的参数了,比如弹出一个窗口选择文件,或者弹出一个选择文件夹的窗体,用于输入的参数。
1) 添加一个选择目录的输入参数
下面我们就是定义了一个输入参数OutputDirectory,在运行的输入参数界面,点击这个参数的输入框就会弹出一个选择目录的窗口。
private string templateOutputDirectory = "";
[Editor(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
[Optional, NotChecked]
[Category("OutputInfo")]
[Description("输出结果的目录。")]
[DefaultValue("")]
public string OutputDirectory
{
get
{
if (string.IsNullOrEmpty(templateOutputDirectory))
{
return "C://"+ (ThisIsDatabase!= null ? ThisIsDatabase.Name : "Output");
}
else
{
return templateOutputDirectory;
}
}
set
{
if (value.EndsWith("//")) value = value.Substring(0, value.Length - 1);
templateOutputDirectory = value;
}
}
2) 添加一个选择文件的输入参数
下面我们就是定义了一个输入参数OutputFile,在运行的输入参数界面,点击这个参数的输入框就会弹出一个选择文件的窗口。
private string templateOutputFile;
[Editor(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
[Optional, NotChecked]
[Category("OutputInfo")]
[Description("输出文件")]
[DefaultValue("")]
public string OutputFile
{
get
{
if (string.IsNullOrEmpty(templateOutputFile))
{
return "C://"+ (ThisIsDatabase != null ? ThisIsDatabase.Name + ".cs" : "Output.cs");
}
else
{
return templateOutputFile;
}
}
set
{
templateOutputFile = value;
}
}
3) 将数据库类型转化为C#类型的函数
输入DbType的类型转化后输出C#的类型的字符串。这个函数很常用到。
public string DataType2CSharpType(System.Data.DbType dbType)
{
switch (dbType)
{
case DbType.AnsiString:
return "string";
case DbType.AnsiStringFixedLength:
return "string";
case DbType.Binary:
return "byte[]";
case DbType.Boolean:
return "bool";
case DbType.Byte:
return "byte";
case DbType.Currency:
return "decimal";
case DbType.Date:
return "DateTime";
case DbType.DateTime:
return "DateTime";
case DbType.DateTime2:
return "DateTime";
case DbType.DateTimeOffset:
return "DateTime";
case DbType.Decimal:
return "decimal";
case DbType.Double:
return "double";
case DbType.Guid:
return "Guid";
case DbType.Int16:
return "short";
case DbType.Int32:
return "int";
case DbType.Int64:
return "long";
case DbType.Object:
return "object";
case DbType.SByte:
return "sbyte";
case DbType.Single:
return "float";
case DbType.String:
return "string";
case DbType.StringFixedLength:
return "string";
case DbType.Time:
return "DateTime";
case DbType.UInt16:
return "ushort";
case DbType.UInt32:
return "uint";
case DbType.UInt64:
return "ulong";
case DbType.VarNumeric:
return "decimal";
case DbType.Xml:
return "string";
default:
return "object";
}
}
4) 获取数据库类型的字段在C#中的默认值
输入DbType的类型转化后输出C#的类型的默认值。这个函数和上面那个差不多,只是有些时候设置了值后希望给个默认值而已。
public string DataTypeDefaultValue(System.Data.DbType dbType)
{
switch (dbType)
{
case DbType.AnsiString:
return "String.Empty";
case DbType.AnsiStringFixedLength:
return "String.Empty";
case DbType.Binary: //Answer modified was just 0
return "new byte[] {}";
case DbType.Boolean:
return "false";
case DbType.Byte: //Answer modified was just 0
return "(byte)0";
case DbType.Currency:
return "0";
case DbType.Date:
return "DateTime.MinValue";
case DbType.DateTime:
return "DateTime.MinValue";
case DbType.DateTime2:
return "DateTime.MinValue";
case DbType.DateTimeOffset:
return "DateTime.MinValue";
case DbType.Decimal:
return "0.0m";
case DbType.Double:
return "0.0f";
case DbType.Guid:
return "Guid.Empty";
case DbType.Int16:
return "(short)0";
case DbType.Int32:
return "(int)0";
case DbType.Int64:
return "(long)0";
case DbType.Object:
return "new object()";
case DbType.SByte:
return "(sbyte)0";
case DbType.Single:
return "0F";
case DbType.String:
return "String.Empty";
case DbType.StringFixedLength:
return "String.Empty";
case DbType.Time:
return "new DateTime(1900,1,1,0,0,0,0)"; //return "DateTime.MaxValue";
case DbType.UInt16:
return "(ushort)0";
case DbType.UInt32:
return "(uint)0";
case DbType.UInt64:
return "(ulong)0";
case DbType.VarNumeric:
return "(decimal)0";
case DbType.Xml:
return "String.Empty";
default:
return "null";
}
}
5) 文件输出函数
当然了,做了这么多的工作,最后肯定是希望输出成文件咯,在前面我们已经说过了,对于输出的结果是调用Render()方法,那么我们只需要在Render()方法里面输出文件就可以了。
public
override void Render(TextWriter writer)
{
if (!Directory.Exists(OutputDirectory))
Directory.CreateDirectory(OutputDirectory);
StreamWriter BaseFile = new StreamWriter(OutputFile, false);
base.Render(writer);
BaseFile.Close();
}
当然了,我们也可以再嵌入的其他模板里面调用这些输出的方法,从而达到输出多个文件的目的,这里就不再详细的写代码了。
另附上完整的B的代码:
<%@
CodeTemplate ResponseEncoding="UTF-8" TargetLanguage="Text" Src="" Inherits="" Debug="False" CompilerVersion="v3.5" Description="这里是模板说明" %>
<%@ Property Category="Context" Description="这是一个数据表" %>
<%@ Assembly %>
<%@ Import Namespace="SchemaExplorer" %>
数据表名称:<%= ThisIsTable.Name %>
<% for (int c = 0; c < ThisIsTable.PrimaryKey.MemberColumns.Count; c++) { %>
主键<%= c %>:<%= ThisIsTable.PrimaryKey.Name %>
<%= ThisIsTable.PrimaryKey.Table.Name %>.<%= ThisIsTable.PrimaryKey.MemberColumns[c].Name %>
<% } %>
<% for (int c = 0; c < ThisIsTable.ForeignKeys.Count; c++) { %>
外键<%= c %>:<%= ThisIsTable.ForeignKeys[c].Name %>
外键<%= c %>对应的列
<% for (int i = 0; i < ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
<%= ThisIsTable.ForeignKeys[c].ForeignKeyTable.Name %>.<%= ThisIsTable.ForeignKeys[c].ForeignKeyMemberColumns[0].Name %> <——来自于 <%= ThisIsTable.ForeignKeys[c].PrimaryKeyTable.Name %>.<%= ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns[0].Name
%>
<% } %>
<% } %>
<% for (int c = 0; c < ThisIsTable.PrimaryKeys.Count; c++) { %>
其他表外键<%= c %>:<%= ThisIsTable.PrimaryKeys[c].Name %>
其他表外键<%= c %>对应的列:
<% for (int i = 0; i < ThisIsTable.PrimaryKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
<%= ThisIsTable.PrimaryKeys[c].PrimaryKeyTable.Name %>.<%= ThisIsTable.PrimaryKeys[c].PrimaryKeyMemberColumns[0].Name %> 作用于——> <%= ThisIsTable.PrimaryKeys[c].ForeignKeyTable.Name %>.<%= ThisIsTable.PrimaryKeys[c].ForeignKeyMemberColumns[0].Name
%>
<% } %>
<% } %>
数据表Select语句:private const String SelectString = @"
SELECT
<% for (int c = 0; c < ThisIsTable.Columns.Count; c++) { %>
[<%= ThisIsTable.Columns[c].Name %>]<% if (c < ThisIsTable.Columns.Count - 1) { %>,<% } %>
<% } %>
FROM [<%= ThisIsTable.Name %>] WHERE 1 = 1 ";
各字段数据类型:
<% for (int c = 0; c < ThisIsTable.Columns.Count; c++) { %>
//数据库类型:DbType.<%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %>
private <%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %> _<%= ThisIsTable.Columns[c].Name %>;
<% } %>
<script runat="template">
//将数据库类型转化为C#类型
public string DataType2CSharpType(System.Data.DbType dbType)
{
switch (dbType)
{
case DbType.AnsiString:
return "string";
case DbType.AnsiStringFixedLength:
return "string";
case DbType.Binary:
return "byte[]";
case DbType.Boolean:
return "bool";
case DbType.Byte:
return "byte";
case DbType.Currency:
return "decimal";
case DbType.Date:
return "DateTime";
case DbType.DateTime:
return "DateTime";
case DbType.DateTime2:
return "DateTime";
case DbType.DateTimeOffset:
return "DateTime";
case DbType.Decimal:
return "decimal";
case DbType.Double:
return "double";
case DbType.Guid:
return "Guid";
case DbType.Int16:
return "short";
case DbType.Int32:
return "int";
case DbType.Int64:
return "long";
case DbType.Object:
return "object";
case DbType.SByte:
return "sbyte";
case DbType.Single:
return "float";
case DbType.String:
return "string";
case DbType.StringFixedLength:
return "string";
case DbType.Time:
return "TimeSpan";
case DbType.UInt16:
return "ushort";
case DbType.UInt32:
return "uint";
case DbType.UInt64:
return "ulong";
case DbType.VarNumeric:
return "decimal";
case DbType.Xml:
return "string";
default:
return "object";
}
}
</script>
OK,终于写完了,花费了一整天的来写,希望对大家有所帮助!
CodeSmith模板生成的更多相关文章
- CodeSmith模板代码生成实战详解
前言 公司项目是基于soa面向服务的架构思想开发的,项目分解众多子项目是必然的.然而子项目的架子结构种类也过多的话,就会对后期的开发维护产生一锅粥的感觉.为了尽可能的在结构层避免出现这种混乱的现象,我 ...
- CodeSmith如何生成实体类
CodeSmith如何生成实体类 这是模板,然后选择对应的表.就可以生成 了 <%-- Name: Database Table Properties Author: Paul Welter D ...
- 使用T4模板生成不同部署环境下的配置文件
在开发企业级应用的时候,通常会有不同的开发环境,比如有开发环境,测试环境,正式环境,生产环境等.在一份代码部署到不同环境的时候,不同环境的配置文件可能需要根据目标环境不同而不同.比如在开发环境中,数据 ...
- CSharpGL(12)用T4模板生成CSSL及其renderer代码
CSharpGL(12)用T4模板生成CSSL及其renderer代码 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立 ...
- MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码
前言 经过前面EF的<第一篇>与<第二篇>,我们的数据层功能已经较为完善了,但有不少代码相似度较高,比如负责实体映射的 EntityConfiguration,负责仓储操作的I ...
- ASP.NET MVC 解析模板生成静态页一(RazorEngine)
简述 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.在早期的MVC版本中默认使用的是ASPX模板引擎,Razor在语法上的确不错,用起来非常方便,简洁的语法 ...
- ccf模板生成
问题描述 成成最近在搭建一个网站,其中一些页面的部分内容来自数据库中不同的数据记录,但是页面的基本结构是相同的.例如,对于展示用户信息的页面,当用户为 Tom 时,网页的源代码是 而当用户为 Jerr ...
- 利用T4模板生成ASP.NET Core控制器的构造函数和参数
前言 在ASP.NET Core中引入了DI,并且通过构造函数注入参数,控制器中会大量使用DI注入各种的配置参数,如果配置注入的参数比较多,而且各个控制器需要的配置参数都基本一样的话,那么不断重复的复 ...
- Visual Studio 2013 EF5实体数据模型 EDMX 使用 T4模板生成后使用 ObjectContext对象
Visual Studio 2013 EF5实体数据模型 EDMX 使用 T4模板生成后的继承对象为DbContext,以前的熟悉的ObjectContext对象不见了,当然使用ObjectConte ...
随机推荐
- Unity3D脚本中文系列教程(十六)
Unity3D脚本中文系列教程(十五) ◆ function OnPostprocessAudio (clip:AudioClip):void 描述:◆ function OnPostprocess ...
- winform中的checkedListbox数据源绑定
首先看清楚一点 winform下该控件的名称叫做:checkedListbox webform下叫做CheckBoxList 不知道这样起名的用意何在,这个别管了,看看用法吧. web下很简单,直接设 ...
- ZOJ3765 Lights Splay树
非常裸的一棵Splay树,需要询问的是区间gcd,但是区间上每个数分成了两种状态,做的时候分别存在val[2]的数组里就好.区间gcd的时候基本上不支持区间的操作了吧..不然你一个区间里加一个数gcd ...
- java基础知识回顾之java Thread类学习(七)--java多线程安全问题(死锁)
死锁:是两个或者两个以上的线程被无限的阻塞,线程之间互相等待所需资源. 线程死锁产生的条件: 当两个线程相互调用Join()方法. 当两个线程使用嵌套的同步代码块的时候,一个线程占用了另一个线程的锁, ...
- hdu 1713 相遇周期
求分数的最小公倍数.对于a/b c/d 先化简为最简分数,分数最小公倍数=分子的最小公倍数/分母的最大公约数. ;}
- 【转】Java读取文件方法大全
本文转自:http://www.cnblogs.com/lovebread/archive/2009/11/23/1609122.html#undefined 目录: 按字节读取文件内容 按字符读取文 ...
- 【Linux高频命令专题(19)】vi/vim
概述 其实在Linux中一切命令或者软件都是文件,所以把vi/vim作为高频命令专题之一,也没什么不妥.虽然大家都称之为编辑器~~ vim是vi的高级版本,比如有代码高亮,也就是说可以把vim定位为程 ...
- 【Linux高频命令专题(10)】mv
概述 mv命令是move的缩写,可以用来移动文件或者将文件改名(move (rename) files),是Linux系统下常用的命令,经常用来备份文件或者目录. 命令格式 mv [选项] 源文件或目 ...
- 什么是spring?
一.对spring的理解. 1.Spring是实现了工厂模式的工厂类(什么是工厂类?简单的来说就是把需要的接口定义到一个类中,需要的时候不用新建,直接从这个类中调用该接口就可以了), 这个类的名字为B ...
- jquery通过ajax-json访问java后台传递参数,通过request.getParameter获取不到参数的说明
http://m.blog.csdn.net/blog/eyebrother/36007145 所以当后台通过request.getParameter("name");对参数值的作 ...