CodeSmith 二、多模板按目錄樹批量自動生成代碼


         通過調用指定目錄下的所有模板,逐一按照數據表生成獨立的代碼文件。支持多模板調用、支持所有數據表生成或批量指定多個生成、支持自動的文件目錄結構、支持代碼文件格式化命名等。                    

背景:最近一個新項目一高興選了Mysql 8,結果出了好幾個麻煩。 Toad for mysql 連不上了,習慣的動軟代碼生成器也連不上了。  還是挺喜歡動軟的傻瓜式操作的,現在沒辦法了試試CodeSmith,折騰了半天終於算是出坑了, 做個筆記免得下次再跳。

 一、需求分析

 大概的需求:

  1.批量選擇表:先選擇數據庫,然后選擇這個數據庫中想生成的表,不選擇則認為是生成全部。

  2.批量選擇模板: 首先想到的是像選擇數據表一樣,后來決定通過選擇目錄的方式,這樣可以將模板按照一定的目錄結構放在一個總目錄中,生成的代碼文件仿照對應模板的目錄結構。

  3.自動生成文件:通過模板的RenderToFile方法自動寫入到文件,不再需要從彈出窗口中復制。

  4.文件名按照一個規則自定義:每個模板可以定義一個名稱規則,如上文的 {0}Model.cs  則會生成文件   UserModel.cs 。

  5.統一設置命名空間:如上例可以在彈出框中設置,但多個模板同時調用的情況下,只需設置一次使多個模板同時生效。

 

二、數據源連接

  點擊右上角的數據源配置,添加一個:

  彈出框點擊Add,出現下面的

  根據對應的數據庫類型選擇即可,mysql連不上的請看上一篇文章:codesmith連接Mysql

 三、創建模板

  首先創建一個最簡單的模板,用於生成實體類,在右上角的Template Explorer中右鍵新建一個Csharp的模板Model.cst:

<%@ CodeTemplate Language="C#" TargetLanguage="C#" Debug="False" %>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context" Description="tableName" %>
<%@ Property Name="FileNameFormat" Type="String" Category="Context" Default="{0}Model.cs" Description="FileName FormatStr"  Optional="True" %>
<%@ Property Name="NameSpace" Type="System.String" Default="" Category="NameSpace" Description="NameSpace"  Optional="True"  %>

<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>

using System;

namespace <%= string.IsNullOrEmpty(NameSpace)?"":NameSpace + "." %>Wx.Model { public class <%= StringUtil.ToPascalCase(SourceTable.Name) %> { <% foreach (ColumnSchema column in this.SourceTable.Columns) { %> public <%= CSharpAlias[column.SystemType.FullName] %> <%= StringUtil.ToPascalCase(column.Name) %> { get; set; } <% } %> } }

 

  右鍵點擊它選擇execute,會彈出對話框讓選擇一個數據表,選擇后點擊生成按鈕,會生成類似如下代碼:

  我要的肯定不是每次選擇一個表,也不想一個個生成之后復制粘貼到項目中去。而且我也不是只需要這樣的一個模板,我要自動生成的有好多。

四、制作用於批量調用的模板

  首先仿照上例新建了幾個模板,例如生成Controller的、ViewModel的,目錄結構如下:

  這些都是具體的“子模板”,然后按照上面的需求新建了一個名為Generate.cst的模板。

 1 <%@ CodeTemplate Language="C#" TargetLanguage="C#"  Debug="True" Description="模板輸出" %>
 2 
 3 <%@ Property Name="NameSpace" Type="System.String" Default="" Category="NameSpace" Optional="True" Description="項目的命名空間"  %>
 4 
 5 <%@ Property Name="SourceDatabase" Type="DatabaseSchema" Default="" Optional="True" Category="數據源" Description="選擇數據庫" %>
 6 <%@ Property Name="SourceTables" Type="SchemaExplorer.TableSchemaCollection" Default="" Optional="True" Category="數據源" Description="選擇數據表,默認空則為全部表" %>
 7 
 8 
 9 <%@ Property Name="TemplateDirectory" Type="String" Editor="System.Windows.Forms.Design.FolderNameEditor" EditorBase="System.Drawing.Design.UITypeEditor" Optional="False" Category="模板" Description="--模板目錄--"%>
10 <%@ Property Name="ExceptPrefix" Type="String" Default="" Optional="True" Category="模板" Description="排除前綴為__的" %>
11 
12 <%@ Property Name="OutputDirectory" Type="String" Editor="System.Windows.Forms.Design.FolderNameEditor" EditorBase="System.Drawing.Design.UITypeEditor" Optional="False" Category="輸出目錄" Description="--輸出目錄--"%>
13 
14 
15 <%@ Assembly Name="System.Design" %>
16 <%@ Assembly Name="SchemaExplorer" %>
17 <%@ Import Namespace="SchemaExplorer" %>
18 
19 <%@ Import Namespace="System.IO" %>
20 <%@ Import Namespace="System.Xml" %>
21 <%@ Import Namespace="System.Text" %>
22 <%@ Import Namespace="System.Windows.Forms.Design" %>
23 <%@ Import Namespace="System.Text.RegularExpressions" %>
24 <%@ Import Namespace="System.Collections.Specialized" %>
25 <%@ Import Namespace="System.Collections.Generic" %>
26 
27 
28 
29 <script runat="template">
30     //模板列表
31     Dictionary<CodeTemplate, string> templates = new Dictionary<CodeTemplate, string>();
32 
33     //入口
34     public void Generate() 35  { 36 GetTemplates(TemplateDirectory); //讀取模板 37 38 int tableIndex = 0; 39 int templateIndex = 0; 40 TableSchemaCollection tables = SourceTables != null && SourceTables.Count > 0 ? SourceTables : SourceDatabase.Tables; //若未手動選擇數據表,則默認為全數據庫 41 foreach(TableSchema SourceTable in tables) 42  { 43 tableIndex++; 44 45 Response.Write(string.Format("{0}.Table {1}",tableIndex, SourceTable.Name)); 46  Response.WriteLine(); 47 templateIndex = 0; 48 foreach(var template in templates) 49  { 50 templateIndex++; 51 Response.Write(string.Format(" {0}.template {1}",templateIndex, template.Key.CodeTemplateInfo.FileName)); 52  Response.WriteLine(); 53 template.Key.SetProperty("NameSpace",NameSpace); //設置統一的命名空間 54 template.Key.SetProperty("SourceTable",SourceTable); //傳入數據表的名稱 55 56 //讀取模板的文件命名格式,生成文件名 57 string FileName = template.Key.GetProperty("FileNameFormat") == null ? SourceTable.Name : string.Format(template.Key.GetProperty("FileNameFormat").ToString(),SourceTable.Name); 58 template.Key.RenderToFile(Path.Combine(template.Value, FileName), true); //按照模板的目錄層級生成文件 59  } 60  Response.WriteLine(); 61  } 62  } 63 64 private void GetTemplates(string directoryStr) 65  { 66 DirectoryInfo directoryInfo = Directory.CreateDirectory(directoryStr); 67  GetTemplates(directoryInfo); 68  } 69 70 //遞歸方式讀取所有滿足要求的模板,記錄模板的目錄結構,生成代碼文件時參照此時的目錄結構 71 private void GetTemplates(DirectoryInfo directoryInfo) 72  { 73 foreach (var file in directoryInfo.GetFiles()) 74  { 75 if (!file.Extension.ToLower().Equals(".cst") || (!string.IsNullOrEmpty(ExceptPrefix) && file.Name.StartsWith(ExceptPrefix))) 76  { 77 continue; 78  } 79 80 CodeTemplateCompiler compiler = new CodeTemplateCompiler(file.FullName); 81 compiler.Compile(); //編譯子模板 82 if (compiler.Errors.Count == 0) 83  { 84  templates.Add(compiler.CreateInstance(),directoryInfo.FullName.Replace(TemplateDirectory, OutputDirectory)); 85  } 86 else 87  { 88 Response.WriteLine("編譯模板" + file.FullName + "錯誤!"); 89  } 90  } 91 92 foreach (var directory in directoryInfo.GetDirectories()) 93  { 94  GetTemplates(directory); 95  } 96  } 97 </script> 98 99 <% this.Generate(); %>

  最上面是各種屬性設置:

  1. NameSpace: 用於設置項目統一的命名空間前綴。

  2. SourceDatabase:可以彈出的對話框中選擇已經配置好的數據庫。

  3. SourceTables:批量選擇數據表,可以按住ctrl或shift多選。

  4. TemplateDirectory:模板所在目錄,支持樹狀目錄結構。

  5. ExceptPrefix:排除模板前綴,前綴為這樣的模板不會被獲取。

  6. OutputDirectory:生成文件存儲目錄,其子目錄結構會按照模板目錄結構。

 

  此模板文件的入口是Generate(),它首先會調用GetTemplates方法讀取屬性TemplateDirectory指定的目錄下的所有模板,並記錄各個模板所在的目錄結構。然后判斷屬性SourceTables是否手動選擇了數據表,如果沒有則為所有表。

  准備工作做好之后,就是遍歷數據表、遍歷模板,生成對應的代碼文件了。具體情況已在代碼中注釋。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM