中國有句古語叫作「工欲善其事,必先利其器」,用通俗的話來講就是「磨刀不誤砍柴功」,古人的這些話告訴咱們:要把事情作好,事先應該準備合適的工具。工具不單單包括器具,數據庫
還包括思想、理論、經驗、道德、法律等一切能解決問題的有形和無形的東西。編程
CodeSmith是一個代碼生成器,能夠用來大量生成代碼的。用起來其實也很簡單,但是許多人都不能入門。大部分的代碼生成工具都是須要模板的,這個很好理解,模板就是一段代碼,ide
裏面留幾個洞,這個洞會被數據庫的字段名或表名等填充,CodeSmith的最多的用法就是鏈接數據庫,而後把數據庫信息取出來去替換用戶提供的模板中關鍵字,這就是代碼生成的原理。工具
爲了生成更靈活,模板和關鍵字能夠混合在一塊兒寫,這個蠻怪異的,不過你看懂了也就無所謂了。學習
當生成應用程序時,不管是編寫數據訪問代碼仍是生成自定義集合,你會發現常常須要重複完成某些特定的任務。這時 CodeSmith 就顯得特別有用,由於你能夠編寫模板自動完成this
這些任務,從而不只提升你的工做效率,並且可以自動完成那些最爲乏味的任務。spa
CodeSmith 的代碼編寫界面跟常見的開發IDE很相似。經常使用的就是Bulid Templete, Generate,以及Output VIEW。3d
1.註釋 <%-- 這是一個C#語言的模板 --%> 2.加載使用訪問數據庫的組件SchemaExplorer,並聲明其使用的命名空間 <%@ Assembly Name="SchemaExplorer" %> <%@ Import Namespace="SchemaExplorer" %> 3.聲明表對象 <%@ Property Name="TargetTable" Type="SchemaExplorer.TableSchema" Category="Context" Description="TargetTable that the object is based on." %> 3.聲明視圖對象 <%@ Property Name="TargetView" Type="SchemaExplorer.ViewSchema" Category="Context" Description="TargetView that the object is based on." %> 4.設置輸入信息框 <%@ Property Name="Author" Type="String" Category="Context" Description="做者" %> 5.編寫C# 語言塊 5.1 <% %> 5.2 <script runat="template"> private string GetDesc(string name) { string temp=string.Empty; temp+="//做者:"+name+" Create Date:"+System.DateTime.Now.ToString(); return temp; } </script> 5.3 建立.cs文件,聲明中src 引用 <%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="Common.cs" Description="指明是一個C#語言版本" Inherits="Common" %> 6.賦值<%= %> 7.相關的數據庫對象 7.1 表名:TargetTable.Name 7.2 表列結合:TargetTable.Columns 7.3 列描述:column.Description
有了上述的語法知識,咱們開始編寫一個簡單的實體對象(Model),最終結果是日誌
//============================================================ ///Create By:QingQing //============================================================ using System; using System.Collections.Generic; using System.Text; namespace POP.Domain { [Serializable()] public class Area { /// <summary> /// /// </summary> public long Areaid {get;set;} /// <summary> /// /// </summary> public string Areaname {get;set;} /// <summary> /// /// </summary> public string Aliasname {get;set;} /// <summary> /// /// </summary> public long? Parentid {get;set;} /// <summary> /// /// </summary> public long? Sortno {get;set;} /// <summary> /// T:有效,F:無效 /// </summary> public string Valid {get;set;} } }
思考一下,using 引用的命名空間是固定的,get set熟悉是固定的,剩下的就是要從數據庫裏獲取表對象進行填充了,上模板。code
<%-- 這是一個C#語言的模板 --%> <%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="Common.cs" Description="指明是一個C#語言版本" Inherits="Common" %> <%-- 加載使用訪問數據庫的組件SchemaExplorer,並聲明其使用的命名空間 --%> <%@ Assembly Name="SchemaExplorer" %> <%@ Import Namespace="SchemaExplorer" %> <%-- 經過這個數據表類型的變量獲得相應的表的信息:TableSchema(表) ViewSchema(視圖) --%> <%@ Property Name="TargetTable" Type="SchemaExplorer.TableSchema" Category="Context" Description="TargetTable that the object is based on." %> <%@ Property Name="Author" Type="String" Category="Context" Description="做者" %> <%--代碼須要的輸入值變量--%> <%@ Property Name="NameSpace" Default="MyTest.DoMain" Type="String" Category="Context" Description="生成代碼是須要輸入的變量" %> <%--<%=GetDesc(Author)%>--%> <% PrintHeader(Author); %> using System; using System.Collections.Generic; using System.Text; namespace <%=NameSpace %> { [Serializable()] public class <%=GetNewTableName(TargetTable.Name)%> { <% foreach (ColumnSchema column in TargetTable.Columns) { %> /// <summary> /// <%=column.Description %> /// </summary> public <%=GetCSharpTypeFromDBFieldType(column) %> <%=GetNewColoumName(column.Name)%> {get;set;} <% } %> } } <script runat="template"> /// <summary> ///// 設置文件描述 /// </summary> /// <param name="name"></param> /// <returns></returns> private string GetDesc(string name) { string temp=string.Empty; temp+="//做者:"+name+" Create Date:" +System.DateTime.Now.ToString(); return temp; } /// <summary> /// 設置文件名稱,後綴名 /// </summary> /// <returns></returns> public override string GetFileName() { return this.TargetTable + ".cs"; } </script>
模板編寫完成,要進行編譯,確認語法是否經過。輸出日誌框,錯誤列表都是咱們的好幫手。
OK,模板編譯經過咱們就要見證奇蹟的時刻了。
批量生成文件
單個文件可以生成了,是否是很方便呢,可是聰明的你確定發現,怎沒有提供批量生成的按鈕呢?對的,這就須要咱們繼續編寫模板來進行實現了。
批量生成要注意一下幾點:
<%@ CodeTemplate Inherits="CodeTemplate" Language="C#" TargetLanguage="Text" Description="生成整個表" Debug="True" ResponseEncoding="UTF-8"%> <%-- 註冊實體層Entity模板 --%> <%@ Register Name="EntityTemplate" Template="BaseForModel.cst" MergeProperties="Flase" ExcludeProperties=""%> <%@ Property Name="Author" Type="String" Category="02.做者" Description="做者" %> <%-- 獲取整個數據庫對象 --%> <%@ Property Name="SourceDatabase" Type="SchemaExplorer.DatabaseSchema" DeepLoad="True" Optional="False" Category="01. 獲取數據庫對象" Description="獲取整個數據庫對象"%> <% //建立實體層Entity類 this.GenerateEntityClasses(); //Debug模式下的信息[Debug="True"] Debug.WriteLine("Success"); %> <script runat="template"> //生成實體Entity類 private void GenerateEntityClasses() { //獲取模板對象 CodeTemplate Template =new EntityTemplate(); foreach(TableSchema table in this.SourceDatabase.Tables) { string FileDirectory = OutputDirectory +"\\"+ GetNewTableName(table.Name) +".cs"; //設置模板的相關內容(Table名稱 ,做者名稱) Template.SetProperty("TargetTable",table); Template.SetProperty("Author",Author); //文件輸出 Template.RenderToFile(FileDirectory,true); Debug.WriteLine(FileDirectory +" 建立成功."); } } /// <summary> /// 獲取新的TableName(首字母大寫,去掉下劃線) /// </summary> /// <param name="name"></param> /// <returns></returns> public string GetNewTableName(string name) { string table=name.Substring(1).ToLower(); string tempTableName=string.Empty; if(table.IndexOf('_')>0) { string[] temp=table.Split('_'); for (int i = 0; i < temp.Length; i++) { tempTableName+=System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(temp[i]); //設置首字母大寫 } } else { tempTableName=System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(table); //設置首字母大寫 } return tempTableName; } //解決方案輸出路徑 private string Directory = String.Empty; [Editor(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor))] [Optional, NotChecked] [DefaultValue("")] public string OutputDirectory { get { return Directory; } set { if (value.EndsWith("\\")) value = value.Substring(0, value.Length -1); Directory = value; } } </script>
CodeSmith 最大的優點就是編寫模板生成符合條件的代碼。其IDE自身提供了不少相關的模板,裏面有不少好用的語法糖。附件提供本身編寫的幾個模板,供你們學習參考。
小夥伴們快快動手編寫屬於本身的模板吧,從繁瑣的任務重脫離出來,咱們的編程更加的愉快。