〇、            前言


          最近兩天自己寫了個簡單的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 %>;


             


          <% } %>


           


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

          http://www.cnblogs.com/sorex/archive/2009/12/24/1631533.html
          posted on 2013-06-15 15:31 sanmao 閱讀(1066) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          常用鏈接

          留言簿(5)

          隨筆分類

          隨筆檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 太和县| 江达县| 社会| 兴业县| 来宾市| 岐山县| 浦东新区| 蒲江县| 西贡区| 离岛区| 寿阳县| 长葛市| 天峻县| 兴国县| 天门市| 江口县| 陆川县| 新泰市| 莱芜市| 延长县| 清河县| 黑龙江省| 灯塔市| 开封市| 科技| 石门县| 聂拉木县| 蕲春县| 顺义区| 岑巩县| 涿鹿县| 瑞昌市| 日土县| 柏乡县| 吉林省| 五大连池市| 博野县| 延津县| 莱州市| 揭东县| 洛川县|