CodeSmith 學習積累

所用工具: CodeSmith Professional v5.1.3.8510,代碼示例全部是以C#爲例。

一、工具設置

(1)CodeSmith默認是不支持中文的,那麼我們必須要先設置使其支持中文顯示,保存。並且要能夠在生成文件中支持中文。

方法一:[Tools->Options...->Studio->Editor->Enable unicode]將這個選項勾上,那麼CodeSmith就可以顯示和保存中文了。

方法二:<%@ CodeTemplate Language="C#" ResponseEncoding="UTF-8" TargetLanguage="Text" %>

(2)[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 Name="SourceDatabase" Type="SchemaExplorer.DatabaseSchema" Category="Required" Description="Database that the stored procedures wrappers should be based on."  IncludeFunctions="True" %>

4)   TableSchemaCollection類型參數聲明:

<%@ Property Name="TDB" Type="SchemaExplorer.TableSchemaCollection" Default="" Optional="False" Category=""%>

5)   TableSchema類型參數聲明:

<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Description="要訪問的表名" %>

(三)    註冊模板區域

在你的模板中可以調用其他的模板用於生成,當然,你調用的模板所需要的參數你都必須給出。註冊代碼如下:

<%@ Register Template="B.cst" MergeProperties="False" ExcludeProperties="" %> 

這就是將B模板註冊到A模板中

(四)  引用聲明區域

在這裏要將我們使用到了的應用集都在這裏寫出來,如果使用到數據庫就一定要添加下面的兩個。

<%@ Assembly Name="SchemaExplorer" %>

<%@ 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>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章