codesmith 入门介绍【转载】 -凯发k8网页登录


最近两天自己写了个简单的orm框架,非常的easy,但是没有相应的代码生成工具,于是就很杯具了!


于是乎,花费了一天的时间学习并写了一个codesmith可以使用的模板。在此记录下codesmith的学习笔记。


所用工具: codesmith professional v5.1.3.8510,代码示例全部是以c#为例。



codesmith默认是不支持中文的,那么我们必须要先设置使其支持中文显示,保存。并且要能够在生成文件中支持中文。



  1. [tools->options...->studio->editor->enable
    unicode]将这个选项勾上,那么codesmith就可以显示和保存中文了。
  2. 在你的模板的最前面的一句话,c#为例:

<%@ codetemplate
targetlanguage="text" src="" inherits="" debug="false" compilerversion="v3.5"
description="template description here." %>


中加入responseencoding="utf-8" 的标签。将会使得生成的文件也支持中文。



  1. [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 %>;


   


<% } %>


 



posted on 2013-06-15 15:31 sanmao 阅读(989) 评论(0)  编辑  收藏

只有注册用户后才能发表评论。


网站导航:
              
 

常用链接

留言簿(5)

搜索

  •  

最新评论

阅读排行榜

评论排行榜

网站地图