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

来源:https://www.cnblogs.com/FlyLolo/archive/2019/03/05/CodeSmith_2.html
-Advertisement-
Play Games

通過調用指定目錄下的所有模板,逐一按照數據表生成獨立的代碼文件。支持多模板調用、支持所有數據表生成或批量指定多個生成、支持自動的文件目錄結構、支持代碼文件格式化命名等。 背景:最近一個新項目一高興選了Mysql 8,結果出了好幾個麻煩。 Toad for mysql 連不上了,習慣的動軟代碼生成器也 ...


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

背景:最近一個新項目一高興選了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是否手動選擇了數據表,如果沒有則為所有表。

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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 安裝配置Maven: 1.1 從Apache網站 http://maven.apache.org/ 下載並且解壓縮安裝Apache Maven 下載: http://maven.apache.org/download.cgi 1.2 配置 Maven 的conf文件夾中配置文件settings ...
  • Scala與Java有著相同的數據類型,Scala數據類型都是對象,Scala中沒有類似Java中那樣的原始類型。Scala 的基本數據類型有: Byte,Short,Int,Long 和 Char (這些成為整數類型)。整數類型加上 Float 和 Double 成為數值類型。此外還有 Strin ...
  • python shell與反彈shell 正常shell需要先在攻擊端開機情況下開啟程式,然後攻擊端運行程式,才能連接 反彈shell,攻擊端是服務端,被攻擊端是客戶端正常shell,攻擊端是客戶端,被攻擊端是服務端 反彈shell,先啟用服務端,再啟用客戶端 反彈shell的好處就是:一旦被攻擊端 ...
  • 前面介紹了集合與映射兩類容器,它們的共同特點是每個元素都是唯一的,並且採用二叉樹方式的類型還自帶有序性。然而這兩個特點也存在弊端:其一,為啥內部元素必須是唯一的呢?像手機店賣出了兩部Mate20,雖然這兩部手機一模一樣,但理應保存兩條銷售記錄才是。其二,不管是哈希類型還是二叉類型,居然都不允許按照加 ...
  • 【路徑】 絕對路徑:從根目錄開始鏈接的路徑 >cd C:\Windows\Boot\DVD\EFI\en-US 相對路徑:不從根目錄開始鏈接的路徑 > cd Boot\DVD\EFI\en-US Python的文件名是以 .py 結尾的 dir是查看當前目錄下的文件cd 路徑 跳轉到指定路徑cd . ...
  • 作者:石杉的架構筆記 寫在前面 春節長假轉眼已過,即將迎來的是一年一度的金三銀四跳槽季。 假如你準備在金三銀四跳槽的話,那麼作為一個Java工程師,應該如何利用1個月的時間,快速的為即將到來的面試進行充分的準備呢? 這兩篇文章,專門站在面試官的角度,給大家分析了平時互聯網公司是如何全方位的考察一個候 ...
  • 1.如果子進程先於父進程退出, 同時父進程又沒有調用wait/waitpid,則該子進程將成為僵屍進程 2.如果fork完就不管了可以使用 忽略子進程信號, 防止僵屍進程 pcntl_signal(SIGCLD, SIG_IGN); 3.如果在主進程中,可以等待子進程的退出 , 這樣也能防止出現僵屍 ...
  • 1、背景:接手公司新項目時,無論用vs2013還是用vs2017都打開不了 2、解決辦法:先把.suo文件刪掉, 結果:vs2013可以打開,vs2017依舊打不開。 3、繼續解決:上網搜了一下,把隱藏的.vs文件夾刪除 結果:完美解決 4、到底與哪一個步驟有關呢?經測試(只刪除.vs文件夾又測試了 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...