一、 工具設(shè)置
CodeSmith默認(rèn)是不支持中文的,那么我們必須要先設(shè)置使其支持中文顯示,保存。并且要能夠在生成文件中支持中文。
[Tools->Options...->Studio->Editor->Enable unicode]將這個(gè)選項(xiàng)勾上,那么CodeSmith就可以顯示和保存中文了。
在你的模板的最前面的一句話,C#為例:
<%@ CodeTemplate TargetLanguage="Text" Src="" Inherits="" Debug="False" CompilerVersion="v3.5" Description="Template description here." %>
中加入ResponseEncoding="UTF-8" 的標(biāo)簽。將會(huì)使得生成的文件也支持中文。
[Tools->Options...->Studio->Editor->Convert tab to]去掉這個(gè)的勾選,就是不使用空格來(lái)替換Tab。
二、 模板區(qū)域說(shuō)明
CodeSmith的模板分為六個(gè)區(qū)域:模板說(shuō)明區(qū)域,屬性設(shè)置區(qū)域,注冊(cè)模板區(qū)域,引用聲明區(qū)域,模板區(qū)域,函數(shù)區(qū)域。
(一) 模板說(shuō)明區(qū)域,只有一句話:
<%@ CodeTemplate ResponseEncoding="UTF-8" TargetLanguage="Text" Src="" Inherits="" Debug="False" CompilerVersion="v3.5" Description="這里是模板說(shuō)明" %>
(二) 屬性設(shè)置區(qū)域
你模板需要那些外接參數(shù),都可以寫(xiě)在這里。當(dāng)然還有一些其他的參數(shù)需要些在函數(shù)區(qū)域,在后面我們?cè)賮?lái)描述。
1) String類型參數(shù)聲明:
<%@ Property Default="AAA" Optional="True" Category="輸入?yún)?shù)" Description="這是一個(gè)字符串型的參數(shù)" %>
2) Bool類型參數(shù)聲明:
<%@ Property Default="True" Optional="False" Category="輸入?yún)?shù)" Description="這是一個(gè)布朗型的參數(shù)" %>
3) DatabaseSchema類型參數(shù)聲明:
<%@ Property Category="Context" Description="這是一個(gè)數(shù)據(jù)庫(kù)" %>
4) TableSchemaCollection類型參數(shù)聲明:
<%@ Property Category="Context" Description="這是一個(gè)數(shù)據(jù)表集合" %>
5) TableSchema類型參數(shù)聲明:
<%@ Property Category="Context" Description="這是一個(gè)數(shù)據(jù)表" %>
(三) 注冊(cè)模板區(qū)域
在你的模板中可以調(diào)用其他的模板用于生成,當(dāng)然,你調(diào)用的模板所需要的參數(shù)你都必須給出。注冊(cè)代碼如下:
<%@ Register Template="B.cst" MergeProperties="False" ExcludeProperties="" %>
這就是將B模板注冊(cè)到A模板中。
(四) 引用聲明區(qū)域
在這里要將我們使用到了的應(yīng)用集都在這里寫(xiě)出來(lái),如果使用到數(shù)據(jù)庫(kù)就一定要添加下面的兩個(gè)。
<%@ Assembly %>
<%@ Import Namespace="SchemaExplorer" %>
要自己控制輸出文件的話就需要添加:<%@ Import Namespace="System.IO" %>
(五) 模板區(qū)域
這里就是我們控制要輸出的文件或者界面的內(nèi)容。
直接輸出值為<%= ThisIsString %>
調(diào)用代碼為<% if (ThisIsBool) { %>A<% } %> 如果ThisIsBool為true則輸出A。
(六) 函數(shù)區(qū)域
在這里我們可以定義我們自己的函數(shù),用于一些復(fù)雜的組合、代碼的重用等。代碼格式和C#完全一樣。
三、 模板編寫(xiě)方法
A. 直接輸出
在模板區(qū)域直接輸入文本,就會(huì)直接輸出的output里面了。
B. 變量輸出
例如輸出ThisIsString的變量值:<%= ThisIsString %>
再例如輸出ThisIsTable的名字:<%= ThisIsTable.Name %>
C. 調(diào)用函數(shù)
例如,如果輸入的ThisIsBool為true就輸出A字符。
<% if (ThisIsBool) { %>A<% } %>
D. 調(diào)用模板
這里我們將在A模板內(nèi)調(diào)用并顯示B模板。每個(gè)模板都有一個(gè)Response來(lái)存儲(chǔ)模板輸出的。模板顯示是調(diào)用Render()方法來(lái)完成的。
<% for(int i = 0; i < ThisIsTableList.Count; i++)
{
B b = new B();
b.ThisIsTable = ThisIsTableList[i];
b.Render(this.Response);
} %>
E. 遍歷Database或TableCollection內(nèi)的表
這里我們可以使用for或者foreach做循環(huán),為了通用性例子全部使用for做循環(huán)。
遍歷ThisIsDatabase并輸出表名
<% for (int t = 0; t < ThisIsDatabase.Tables.Count; t++) { %>
<%= ThisIsDatabase.Tables[t].Name %>
<% } %>
F. 遍歷Table的列
遍歷ThisIsTable的列并且生成類似如下格式的語(yǔ)句:
//數(shù)據(jù)庫(kù)類型:DbType.int
private int _ID;
這里調(diào)用了一個(gè)方法DataType2CSharpType(System.Data.DbType dbType)在后面將會(huì)講到。
<% for (int c = 0; c < ThisIsTable.Columns.Count; c++) { %>
//數(shù)據(jù)庫(kù)類型:DbType.<%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %>
private <%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %> _<%= ThisIsTable.Columns[c].Name %>;
<% } %>
輸出結(jié)果:
//數(shù)據(jù)庫(kù)類型:DbType.int
private int _ID;
//數(shù)據(jù)庫(kù)類型:DbType.int
private int _ClassID;
//數(shù)據(jù)庫(kù)類型: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 %>
<% } %>
輸出結(jié)果 :
主鍵0:PK_Student
Student.ID
H. 遍歷Table的FK(Table自己是外鍵表<即Table為明細(xì)表>)
這里說(shuō)明下,下面的代碼僅僅只是對(duì)FK里面的列是一對(duì)一的有效,如果是多對(duì)多的FK需要修改下面的0的地方為循環(huán)即可。
<% for (int c = 0; c < ThisIsTable.ForeignKeys.Count; c++) { %>
外鍵<%= c %>:<%= ThisIsTable.ForeignKeys[c].Name %>
外鍵<%= c %>對(duì)應(yīng)的列
<% for (int i = 0; i < ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
<%= ThisIsTable.ForeignKeys[c].ForeignKeyTable.Name %>.<%= ThisIsTable.ForeignKeys[c].ForeignKeyMemberColumns[0].Name %> <——來(lái)自于 <%= ThisIsTable.ForeignKeys[c].PrimaryKeyTable.Name %>.<%= ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns[0].Name %>
<% } %>
<% } %>
輸出結(jié)果:
外鍵0:FK_Student_Class
外鍵0對(duì)應(yīng)的列
I. 遍歷Table的FK(Table自己是主鍵表<即Table為父表>)
<% for (int c = 0; c < ThisIsTable.PrimaryKeys.Count; c++) { %>
其他表外鍵<%= c %>:<%= ThisIsTable.PrimaryKeys[c].Name %>
其他表外鍵<%= c %>對(duì)應(yīng)的列:
<% 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 %>
<% } %>
<% } %>
輸出結(jié)果:
其他表外鍵0:FK_ExamScore_Student
其他表外鍵0對(duì)應(yīng)的列:
Student.ID 作用于——> ExamScore.StudentID
四、 函數(shù)區(qū)域用法
之前我們提到過(guò),有些參數(shù)必須要寫(xiě)在函數(shù)區(qū)域中。當(dāng)然這些參數(shù)就是需要有一些其他組件支持的參數(shù)了,比如彈出一個(gè)窗口選擇文件,或者彈出一個(gè)選擇文件夾的窗體,用于輸入的參數(shù)。
1) 添加一個(gè)選擇目錄的輸入?yún)?shù)
下面我們就是定義了一個(gè)輸入?yún)?shù)OutputDirectory,在運(yùn)行的輸入?yún)?shù)界面,點(diǎn)擊這個(gè)參數(shù)的輸入框就會(huì)彈出一個(gè)選擇目錄的窗口。
private string templateOutputDirectory = "";
[Editor(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
[Optional, NotChecked]
[Category("OutputInfo")]
[Description("輸出結(jié)果的目錄。")]
[DefaultValue("")]
public string OutputDirectory
{
get
{
if (string.IsNullOrEmpty(templateOutputDirectory))
{
return "C://"+ (ThisIsDatabase!= null ? ThisIsDatabase.Name : "Output");
}
else
{
return templateOutputDirectory;
}
}
set
{
if (value.EndsWith("http://")) value = value.Substring(0, value.Length - 1);
templateOutputDirectory = value;
}
}
2) 添加一個(gè)選擇文件的輸入?yún)?shù)
下面我們就是定義了一個(gè)輸入?yún)?shù)OutputFile,在運(yùn)行的輸入?yún)?shù)界面,點(diǎn)擊這個(gè)參數(shù)的輸入框就會(huì)彈出一個(gè)選擇文件的窗口。
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) 將數(shù)據(jù)庫(kù)類型轉(zhuǎn)化為C#類型的函數(shù)
輸入DbType的類型轉(zhuǎn)化后輸出C#的類型的字符串。這個(gè)函數(shù)很常用到。
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) 獲取數(shù)據(jù)庫(kù)類型的字段在C#中的默認(rèn)值
輸入DbType的類型轉(zhuǎn)化后輸出C#的類型的默認(rèn)值。這個(gè)函數(shù)和上面那個(gè)差不多,只是有些時(shí)候設(shè)置了值后希望給個(gè)默認(rèn)值而已。
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) 文件輸出函數(shù)
當(dāng)然了,做了這么多的工作,最后肯定是希望輸出成文件咯,在前面我們已經(jīng)說(shuō)過(guò)了,對(duì)于輸出的結(jié)果是調(diào)用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();
}
當(dāng)然了,我們也可以再嵌入的其他模板里面調(diào)用這些輸出的方法,從而達(dá)到輸出多個(gè)文件的目的,這里就不再詳細(xì)的寫(xiě)代碼了。
另附上完整的B的代碼:
<%@ CodeTemplate ResponseEncoding="UTF-8" TargetLanguage="Text" Src="" Inherits="" Debug="False" CompilerVersion="v3.5" Description="這里是模板說(shuō)明" %>
<%@ Property Category="Context" Description="這是一個(gè)數(shù)據(jù)表" %>
<%@ Assembly %>
<%@ Import Namespace="SchemaExplorer" %>
數(shù)據(jù)表名稱:<%= 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 %>對(duì)應(yīng)的列
<% for (int i = 0; i < ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
<%= ThisIsTable.ForeignKeys[c].ForeignKeyTable.Name %>.<%= ThisIsTable.ForeignKeys[c].ForeignKeyMemberColumns[0].Name %> <——來(lái)自于 <%= 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 %>對(duì)應(yīng)的列:
<% 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 %>
<% } %>
<% } %>
數(shù)據(jù)表Select語(yǔ)句: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 ";
各字段數(shù)據(jù)類型:
<% for (int c = 0; c < ThisIsTable.Columns.Count; c++) { %>
//數(shù)據(jù)庫(kù)類型:DbType.<%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %>
private <%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %> _<%= ThisIsTable.Columns[c].Name %>;
<% } %>
<script runat="template">
//將數(shù)據(jù)庫(kù)類型轉(zhuǎn)化為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>
聯(lián)系客服