1. 程式人生 > >利用CodeSmith在自己的工程中動態生成程式碼

利用CodeSmith在自己的工程中動態生成程式碼


這一個星期都在與程式碼生成器在奮戰。

一開始,打算採用T4模板引摯。經過兩天研究,發現困難很大。T4的設計,是與IDE綁在一起,而且每個visual studio版本,繫結越來越緊,越來越不相容。

所以,還是打算採用CodeSmith.

一年多沒用CodeSmith(原來也不會用),好不容易找到安裝包還有一個重要的示例:


http://www.codeproject.com/Articles/17065/Code-Generator-using-CodeSmith-Api

這個示例,比較清楚地寫出瞭如何呼叫CodeSmith API,通過模板,生成程式碼:

但是,這個作者比較小氣,沒有公開原碼。我也不清楚為什麼,可能也有自己的原因。

所以,我反編譯過了,找到了程式碼:

            CodeTemplateCompiler compiler;
            GenericProperty property = (GenericProperty) this.properties.GetProperty("Template Path", "Paths");
            GenericProperty property2 = (GenericProperty) this.properties.GetProperty("Code Path", "Paths");
            GenericProperty property1 = (GenericProperty) this.properties.GetProperty("SourceTable", "Database");
            GenericProperty property3 = (GenericProperty) this.properties.GetProperty("IncludeDelete", "StoreProcedure Options");
            GenericProperty property4 = (GenericProperty) this.properties.GetProperty("IncludeDrop", "StoreProcedure Options");
            GenericProperty property5 = (GenericProperty) this.properties.GetProperty("IncludeInsert", "StoreProcedure Options");
            GenericProperty property6 = (GenericProperty) this.properties.GetProperty("IncludeUpdate", "StoreProcedure Options");
            GenericProperty property7 = (GenericProperty) this.properties.GetProperty("IncludeGet", "StoreProcedure Options");
            GenericProperty property8 = (GenericProperty) this.properties.GetProperty("IncludeGetList", "StoreProcedure Options");
            GenericProperty property9 = (GenericProperty) this.properties.GetProperty("DeletePrefix", "StoreProcedure Style");
            GenericProperty property10 = (GenericProperty) this.properties.GetProperty("InsertPrefix", "StoreProcedure Style");
            GenericProperty property11 = (GenericProperty) this.properties.GetProperty("SelectPrefix", "StoreProcedure Style");
            GenericProperty property12 = (GenericProperty) this.properties.GetProperty("UpdatePrefix", "StoreProcedure Style");
            GenericProperty property15 = (GenericProperty) this.properties.GetProperty("Entire DataBase", "Database");
            GenericProperty property13 = (GenericProperty) this.properties.GetProperty("NameSpace", "NameSpace");
            GenericProperty property14 = (GenericProperty) this.properties.GetProperty("DotNet Version", "Version");
            if (!this.rbDatabase.Checked)
            {
                try
                {
                    this.timePB.Interval = 100;
                    this.timePB.Start();
                    compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\Entity.cst");
                    compiler.Compile();
                    if (compiler.Errors.Count == 0)
                    {
                        CodeTemplate template = compiler.CreateInstance();
                        DatabaseSchema schema = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text);
                        TableSchema schema2 = schema.Tables[this.tbName.SelectedItem.ToString()];
                        template.SetProperty("NameSpace", property13.Value.ToString());
                        template.SetProperty("SourceTable", schema2);
                        template.RenderToFile(property2.Value.ToString() + @"\Entity\" + schema2.Name + ".cs", true);
                    }
                    else if (compiler.Errors.Count > 0)
                    {
                        MessageBox.Show(compiler.Errors.ToString());
                    }
                    compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\EntityBase.cst");
                    compiler.Compile();
                    if (compiler.Errors.Count == 0)
                    {
                        CodeTemplate template2 = compiler.CreateInstance();
                        DatabaseSchema schema3 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text);
                        TableSchema schema4 = schema3.Tables[this.tbName.SelectedItem.ToString()];
                        template2.SetProperty("NameSpace", property13.Value.ToString());
                        template2.SetProperty("SourceTable", schema4);
                        template2.RenderToFile(property2.Value.ToString() + @"\Entity\Base\" + schema4.Name + "Base.cs", true);
                    }
                    else if (compiler.Errors.Count > 0)
                    {
                        MessageBox.Show(compiler.Errors.ToString());
                    }
                    compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\DataProvider.cst");
                    compiler.Compile();
                    if (compiler.Errors.Count == 0)
                    {
                        CodeTemplate template3 = compiler.CreateInstance();
                        DatabaseSchema schema5 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text);
                        TableSchema schema6 = schema5.Tables[this.tbName.SelectedItem.ToString()];
                        template3.SetProperty("NameSpace", property13.Value.ToString());
                        template3.SetProperty("SourceTable", schema6);
                        template3.RenderToFile(property2.Value.ToString() + @"\Entity\" + schema6.Name + "DataProvider.cs", true);
                    }
                    else if (compiler.Errors.Count > 0)
                    {
                        MessageBox.Show(compiler.Errors.ToString());
                    }
                    if (property14.Value.Equals("2003"))
                    {
                        compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\DataProviderBase1.cst");
                    }
                    else
                    {
                        compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\DataProviderBase.cst");
                    }
                    compiler.Compile();
                    if (compiler.Errors.Count == 0)
                    {
                        CodeTemplate template4 = compiler.CreateInstance();
                        DatabaseSchema schema7 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text);
                        TableSchema schema8 = schema7.Tables[this.tbName.SelectedItem.ToString()];
                        template4.SetProperty("NameSpace", property13.Value.ToString());
                        template4.SetProperty("SourceTable", schema8);
                        template4.RenderToFile(property2.Value.ToString() + @"\Entity\Base\" + schema8.Name + "DataProviderBase.cs", true);
                    }
                    else if (compiler.Errors.Count > 0)
                    {
                        MessageBox.Show(compiler.Errors.ToString());
                    }
                    compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\EntityControl.cst");
                    compiler.Compile();
                    if (compiler.Errors.Count == 0)
                    {
                        CodeTemplate template5 = compiler.CreateInstance();
                        DatabaseSchema schema9 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text);
                        TableSchema schema10 = schema9.Tables[this.tbName.SelectedItem.ToString()];
                        template5.SetProperty("NameSpace", property13.Value.ToString());
                        template5.SetProperty("SourceTable", schema10);
                        template5.RenderToFile(property2.Value.ToString() + @"\Entity\" + schema10.Name + "Control.cs", true);
                    }
                    else if (compiler.Errors.Count > 0)
                    {
                        MessageBox.Show(compiler.Errors.ToString());
                    }
                    if (property14.Value.Equals("2003"))
                    {
                        compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\EntityControlBase1.cst");
                    }
                    else
                    {
                        compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\EntityControlBase.cst");
                    }
                    compiler.Compile();
                    if (compiler.Errors.Count == 0)
                    {
                        CodeTemplate template6 = compiler.CreateInstance();
                        DatabaseSchema schema11 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text);
                        TableSchema schema12 = schema11.Tables[this.tbName.SelectedItem.ToString()];
                        template6.SetProperty("NameSpace", property13.Value.ToString());
                        template6.SetProperty("SourceTable", schema12);
                        template6.RenderToFile(property2.Value.ToString() + @"\Entity\Base\" + schema12.Name + "ControlBase.cs", true);
                    }
                    else if (compiler.Errors.Count > 0)
                    {
                        MessageBox.Show(compiler.Errors.ToString());
                    }
                    compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\StoredProcedures.cst");
                    compiler.Compile();
                    if (compiler.Errors.Count == 0)
                    {
                        CodeTemplate template7 = compiler.CreateInstance();
                        DatabaseSchema schema13 = new DatabaseSchema(new SqlSchemaProvider(), "Server=" + this.cbServer.SelectedItem.ToString() + ";Database=" + this.dbName.SelectedItem.ToString() + ";uid=" + this.tbUserid.Text + ";pwd=" + this.tbPwd.Text);
                        TableSchema schema14 = schema13.Tables[this.tbName.SelectedItem.ToString()];
                        template7.SetProperty("SourceTable", schema14);
                        template7.SetProperty("IncludeDelete", property3.Value.ToString());
                        template7.SetProperty("IncludeDrop", property4.Value.ToString());
                        template7.SetProperty("IncludeInsert", property5.Value.ToString());
                        template7.SetProperty("IncludeUpdate", property6.Value.ToString());
                        template7.SetProperty("IncludeGet", property7.Value.ToString());
                        template7.SetProperty("IncludeGetList", property8.Value.ToString());
                        template7.SetProperty("DeletePrefix", property9.Value.ToString());
                        template7.SetProperty("InsertPrefix", property10.Value.ToString());
                        template7.SetProperty("SelectPrefix", property11.Value.ToString());
                        template7.SetProperty("UpdatePrefix", property12.Value.ToString());
                        template7.RenderToFile(property2.Value.ToString() + @"\Entity\Sp\" + schema14.Name + "StoredProcedures.sql", true);
                    }
                    else if (compiler.Errors.Count > 0)
                    {
                        MessageBox.Show(compiler.Errors.ToString());
                    }
                    compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\GenericList.cst");
                    compiler.Compile();
                    if (compiler.Errors.Count == 0)
                    {
                        CodeTemplate template8 = compiler.CreateInstance();
                        template8.SetProperty("NameSpace", property13.Value.ToString());
                        template8.RenderToFile(property2.Value.ToString() + @"\Entity\GenericList.cs", true);
                    }
                    else if (compiler.Errors.Count > 0)
                    {
                        MessageBox.Show(compiler.Errors.ToString());
                    }
                    compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\CBO.cst");
                    compiler.Compile();
                    if (compiler.Errors.Count == 0)
                    {
                        CodeTemplate template9 = compiler.CreateInstance();
                        template9.SetProperty("NameSpace", property13.Value.ToString());
                        template9.RenderToFile(property2.Value.ToString() + @"\Entity\CBO.cs", true);
                    }
                    else if (compiler.Errors.Count > 0)
                    {
                        MessageBox.Show(compiler.Errors.ToString());
                    }
                    this.timePB.Stop();
                    this.ProgressBar1.Value = 0;
                    ConfirmMsg msg = new ConfirmMsg();
                    msg.linkLabel1.Text = property2.Value.ToString() + @"\Entity";
                    msg.linkLabel1.Links.Add(0, 100, property2.Value.ToString() + @"\Entity");
                    msg.Show();
                }
                catch (Exception exception)
                {
                    this.timePB.Stop();
                    this.ProgressBar1.Value = 0;
                    MessageBox.Show(exception.Message.ToString());
                }
            }

最關鍵就是這兩句:

                    compiler = new CodeTemplateCompiler(property.Value.ToString() + @"\Entity.cst");
                    compiler.Compile();

然而,意想不到的事情發生了。

沒想到CodeSmith公司,更是小氣,CodeSmith.Engine.dll 競然,需要license才可以被呼叫,我了個去,有這麼黑的嗎?

原來用的是4.1.1,然後到網上,找了一天多,終於找到5.3有破解的CodeSmith.Engine.dll庫。

http://download.csdn.net/detail/meanshe/3949350

真是救了我的工作啊。

感謝上帝。

否則,我可能就得自己親自動手來破解了。可能又得幾天。


另外,我的程式碼裡,有兩處注掉了,如果你已有資料庫,想讓介面每次彈出,都事先寫好資訊,就把那些程式碼反注掉:

第一處:

        public CodeGenerator()
        {
            this.InitializeComponent();
            this.GetServerName();
            this.comboBox1.SelectedIndex = 1;

            //如果不想每次都輸入使用者密碼,就開啟這些註釋
            //tbUserid.Text = "sa";
            //tbPwd.Text = "123456";  //haoyujie
        }


第二處:

        private void CodeGenerator_Load(object sender, EventArgs e)
        {
            this.properties = new GenericPropertyCollection_CustomTypeDescriptor();
            this.properties.AddProperty(new GenericProperty("NameSpace", "PIMail", "NameSpace", "This is the NameSpace of the project", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("Entire DataBase", "True", "DataBase", "Is Code generated for whole database or not", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("IncludeDelete", "True", "StoreProcedure Options", "Is Delete StoreProcedure Included or not", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("IncludeDrop", "True", "StoreProcedure Options", "Is Drop Script Included or not", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("IncludeInsert", "True", "StoreProcedure Options", "Is Insert Script Included or not", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("IncludeUpdate", "True", "StoreProcedure Options", "Is Update Script Included or not", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("IncludeGet", "True", "StoreProcedure Options", "Is Get Script Included or not", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("IncludeGetList", "True", "StoreProcedure Options", "Is GetList Script Included or not", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("DeletePrefix", "Delete", "StoreProcedure Style", "the prefix for delete store procedure", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("InsertPrefix", "Add", "StoreProcedure Style", "the prefix for Add store procedure", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("SelectPrefix", "Select", "StoreProcedure Style", "the prefix for Select store procedure", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("UpdatePrefix", "Update", "StoreProcedure Style", "the prefix for Update store procedure", new Attribute[0]));
            this.properties.AddProperty(new GenericProperty("DotNet Version", "2003", "Version", "The DotNet Version ", new Attribute[0]));
            this.propertyGrid1.SelectedObject = this.properties;
            this.propertyGrid1.Refresh();


            //如果不想每次都輸入使用者密碼,就開啟這些註釋
            //haoyujie
         //   this.GetConnection();
   

         //   string curDatabaseName = "AutoPack";
         //this.dbName.SelectedText = curDatabaseName;
         //   if (!this.Added)   //標記屬性框裡,是否有
         //   {
         //       AddDatabaseName(curDatabaseName);
         //   }
         //   else
         //   {
         //       ModifyDatabaseName(curDatabaseName);
         //   }
         //   this.dbName.SelectedIndex = 0;
         //   this.dbtoolStripComboBox2.SelectedIndex = this.dbName.SelectedIndex;

         //   this.rbDatabase.Checked = false;
         //   this.rbTable.Checked = true;

         //   tbName.SelectedItem = "TBL_TREE_HIERARCHY";
         //   //////////////////////////////////////////////////////////////////////////
         //   this.tbTemplate.Text = "E:\\tmp\\Final_Templates";

         //   this.properties.AddProperty(new GenericProperty("Template Path", this.tbTemplate.Text, "Paths", "The path where the templates are place", new Attribute[0]));
         //   this.propertyGrid1.Refresh();
         //   this.tempathAdded = true;
         //   //////////////////////////////////////////////////////////////////////////
         //   this.tbCode.Text = "E:\\tmp\\tmpcodeout";

         //   this.properties.AddProperty(new GenericProperty("Code Path", this.tbCode.Text, "Paths", "The path where the templates are place", new Attribute[0]));
         //   this.propertyGrid1.Refresh();
         //   this.codepathAdded = true;

         //   try
         //   {
         //       DirectoryInfo info = new DirectoryInfo(this.tbCode.Text);
         //       info.CreateSubdirectory("Entity");
         //       info.CreateSubdirectory(@"Entity\Base");
         //       info.CreateSubdirectory(@"Entity\Sp");
         //   }
         //   catch (Exception exception)
         //   {
         //       MessageBox.Show(exception.Message.ToString());
         //   }

        }


這是我反編譯後的程式碼,邊窗體都做好了。方便大家學習。

如果有人認為我冒犯了他的權益,就聯絡我。

等了半天,還沒出天,哪天出來,我把連結放在這裡。

程式碼下載:

另外,請CSDN的編輯們放心,我所反編譯的程式碼,原作者是提供原碼的。

只是現在找不到原碼了。所以,我這也不算什麼過分。

相關推薦

利用CodeSmith自己工程動態生成程式碼

這一個星期都在與程式碼生成器在奮戰。 一開始,打算採用T4模板引摯。經過兩天研究,發現困難很大。T4的設計,是與IDE綁在一起,而且每個visual studio版本,繫結越來越緊,越來越不相容。 所以,還是打算採用CodeSmith. 一年多沒用CodeSmith(原來

AbstractProcessor: 利用註解動態生成程式碼

按照處理時期,註解分為兩種型別,一種是執行時註解,另一種是編譯時註解。 編譯時註解的核心依賴APT(Annotation Processing Tools)實現,對應的處理流程為: 在某些程式碼元素上(如型別、函式、欄位等)添加註解; 編譯時編譯器會檢查A

關於jQuery動態生成的點擊事件觸發兩次的討論

get com pan .html 方法 執行 url wall itl 由於是動態生成的 點擊事件運用了jQuery裏面的on()方法,綁定在body上面,結果在程序裏面運行了兩次。參考了博客 利用on和off方法編寫高效的js代碼知道了很多在dom對象刪除以後,其聲明

Java動態生成當前日期的文件

java;文件名自動生成;1.Java中動態生成當前日期的文件名稱並且將控制臺的輸出信息輸入到文件中 public static void SaveClonseToFile() throws IOException, FileNotFoundException { File f =

Jqgrid動態生成colModel實現雙擊編輯整列時,鼠標定位在當前雙擊指定單元格

jqGrid使用鼠標定位雙擊的單元格通過配置ondbclick事件來實現雙擊功能ondblClickRow:function(rowid,iRow,iCol,e) {//獲取表格的初始model var colModel =$(TableId).jqG

在Vue項目動態生成二維碼 阿星小棧

logs console toc ons template imp return important 轉換 一、使用jquery.qrcode生成二維碼 1、首先在頁面中加入jquery庫文件和qrcode插件 <script type="text/javascri

lua裡實現類似巨集定義,動態生成程式碼

其實就是用了  lua 的 loadstring 功能。 1.把需要動態生成的程式碼拼接成為一個字串。 str 2. loadstring(str)   這個只是解析了程式碼,相當於一個function   需要 執行一下才會生效

程式碼遷移攻略:在Java工程呼叫Python程式碼

Python是一門好用的指令碼語言,底層基於C實現,快速且簡單。使用python可以說是站在巨人肩膀上程式設計,使得程式設計師更專注於業務及邏輯,而不是被人學爛的語言工具。但是團隊合作時候,就會有一些多

SQLITE 原始碼在自己工程的使用

為什麼會有這種需求,因為sqlite的原始碼是純C語言,對於不想額外安裝exe的場合,可以把原始碼嵌入到任何你需要的工程中來使用。 首先,去官網下載到sqlite的原始碼,http://www.sq

百度地圖動態生成網格

目的:根據距離生成網格,比如500米一個網格 技術:js 百度地圖 程式碼如此下: <!DOCTYPE html> <html> <head>     <meta http-equiv="Content-

Js動態追加程式碼後,之前定義的Js不再起作用

 問題描述:在js檔案中使用javaScript或者jQuery中的html('程式碼')或者append('程式碼'),將我們的html程式碼動態新增到指定的容器裡面(例如:table)後,頁面可以正常顯示,但是所追加部分的頁面的js會失效。 解決方法:採用JQuery中的 de

layui laydate 渲染失效問題,lay-key導致動態生成程式碼二次渲染失敗

在開發中因為需要動態生成時間選擇框,所以選擇了layui的 laydate控制元件,但是遇到了生成的時間選擇框點選無效的問題,然後再次render 時間選擇器一閃就消失了,查了多方資料,找到了如下的解決方法 首先來看下寫的demo程式碼 首先是 html程式

mybatis逆向工程,自動生成程式碼

mybatis作為一種半自動化的ORM持久型框架,最大的好處就是我們可以對sql語句進行調優,但在使用mybatis的過程中,我們也總是在不停的寫model類 、dao介面、mapper對映檔案,實際開發中也很耗時,也可能會出錯,得益於mybatis-generator工具

js動態生成表格

  <script type="text/javascript"> function demo() { // 獲取輸入框內輸入的行和列的數值 var rowValue = parseInt

dll工程如何生成lib檔案

新建了一個dll工程,除了生成dll檔案外,你還想生成相應的lib檔案,怎麼搞? 解決辦法: 為工程新增一個def檔案即可。 注意: 新增def檔案後,預設情況下,生成的lib檔案的名字與工程名字相同; 如果你想使用自定義的lib檔名,修改def的檔案內容即可。

在Delphi動態生成QuickReport報表

----筆者在前一段使用Delphi開發資料庫的工作中,使用者提出了這樣一個需求:要根據自己的的查詢結果動態生成報表然後進行列印。幾經摸索,筆者使用動態生成QuickReport控制元件的方法滿足了使用者的需求。現將此方法說明如下,希望能為有類似工作要做的朋友們提供一點有益的提示。  <?xml:na

HTML動態生成內容的事件繫結問題

        在實際開發過程中,有時需要向頁面中動態的插入html內容,並在插入的節點中繫結事件處理函式。         用Javascript向HTML文件中插入內容,有兩種方法,一種是JS建立節點,然後插入到html中;另外一種是通過ajax非同步載入的方式,從伺服

關於js動態生成的點選事件觸發兩次的討論

由於是動態生成的  點選事件運用了jQuery裡面的on()方法,繫結在body上面,結果在程式裡面運行了兩次。參考了部落格 利用on和off方法編寫高效的js程式碼知道了很多在dom物件刪除以後

freemarker 替換字串,模板,可以用來動態生成程式碼

freemarker 通過字串模板生成,會把map中 name 對應的變數替換字串模板中的${name} package com.thinkgem.jeesite.test.test; import

Java工程嵌入scala程式碼

今天我將介紹如何在Java工程使用Scala程式碼。對於那些想在真實場景中嘗試使用Scala的開發人員來說,會非常有意思。這和你專