最近在用layui做后台管理,增刪改查這些一成不變的東西寫起來浪費大量時間,於是做了個簡單的代碼生成器快速生成
代碼生成器的原理其實很簡單,都是基於模板實現替換,Razor是個不錯的選擇(或者Nvelocity。。),還可以用字符串占位符替換的方式生成。
1. 技術棧
0.Asp.net
1.模板引擎RazorEngine
2.ORM使用SqlSugar
3.生成壓縮包SharpZipLib
2.源碼下載
https://gitee.com/huzhihao/code_generator.git
3.代碼分析
核心代碼就兩個cs:
Coder.cs
------------------------------------------
using MySqlSugar; using RazorEngine; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace ConsoleApp1 { public class Coder { private SqlSugarClient _sqlsugarClient; public SqlSugarClient db { get { if (_sqlsugarClient == null) { var conn = "Database=easycms;Data Source=127.0.0.1;User Id=root;Password=root;pooling=false;CharSet=utf8;port=3306;SslMode=None"; var db = new SqlSugarClient(conn); _sqlsugarClient = db; } return _sqlsugarClient; } } public string entity_template { get; set; } public string dto_template { get; set; } public string app_template { get; set; } public string ctrl_template { get; set; } /// <summary> /// 數據庫名 /// </summary> public string dbschema { get; set; } public Coder() { var path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Template", "實體類razor.txt"); entity_template = File.ReadAllText(path); var dto_path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Template", "DTO類Razor.txt"); dto_template = File.ReadAllText(dto_path); var app_path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Template", "應用類razor.txt"); app_template = File.ReadAllText(app_path); var ctrl_path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Template", "控制器razor.txt"); ctrl_template = File.ReadAllText(ctrl_path); dbschema = "easycms"; } public string Builder() { var keyword = "sys_user,sys_dict,sys_parameter,sys_role"; var dir = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "CodeGenerate"); if (Directory.Exists(dir)) { Directory.Delete(dir, true); } StringBuilder builder = new StringBuilder(); var tables = db.SqlQuery<TableInfo>(string.Format(@"select table_name,table_comment from information_schema.tables where table_schema='{0}'", dbschema)).ToList(); foreach (var tb in keyword.Split(',')) { var tablecomment = tables.Find(c => c.table_name == tb).table_comment; var ret = RazorParse(tb, tablecomment); builder.Append(ret); } var srcdir = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "CodeGenerate", "Code"); var folders = new List<string>(); folders.Add(srcdir); var bl = new ZipHelper().ZipManyFilesOrDictorys(folders.AsEnumerable(), Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "CodeGenerate", "Code.zip"), ""); return builder.ToString(); ; } public string RazorParse(string tablename, string tablecomment) { StringBuilder builder = new StringBuilder(); var columsInfo = db.SqlQuery<ColumnInfo>(string.Format(@"select table_name,column_name,ordinal_position,is_nullable,data_type,character_maximum_length,column_key,column_comment from information_schema.COLUMNS where table_schema = '{0}' and table_name = '{1}'", dbschema, tablename)).ToList(); foreach (var item in columsInfo) { item.data_type = Utils.GetCsType(item.data_type); if (!item.data_type.Equals("string") && item.is_nullable.Equals("YES")) { item.data_type = item.data_type + "?"; } } #region entity var entity_result = Razor.Parse(entity_template, new { EntityNameSpace = "Ace.Entity.CMS", EntityName = tablename, Columns = columsInfo },"entity"); Utils.Save( Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "CodeGenerate\\Code\\Entity", $"{tablename}.cs") , entity_result); builder.Append(entity_result); #endregion #region dto var dto_result = Razor.Parse(dto_template, new { DtoNameSpace = "Ace.Application.CMS.Models", DtoName = Utils.ToCamelName(tablename) + "Info", Columns = columsInfo },"dto"); Utils.Save( Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "CodeGenerate\\Code\\Dto", $"{Utils.ToCamelName(tablename) + "Info"}.cs") , dto_result); builder.Append(dto_result); #endregion #region app var app_result = Razor.Parse(app_template, new { AppNameSpace = "Ace.Application.CMS.Implements", DtoName = Utils.ToCamelName(tablename) + "Info", AppClassName = Utils.ToCamelName(tablename), Table = tablename, Columns = columsInfo },"app"); Utils.Save( Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "CodeGenerate\\Code\\Application", $"{Utils.ToCamelName(tablename) + "Service"}.cs") , app_result); builder.Append(app_result); #endregion #region controller var ctrl_result = Razor.Parse(ctrl_template, new { AppClassName = Utils.ToCamelName(tablename), DtoName = Utils.ToCamelName(tablename) + "Info", TableComment = tablecomment, },"ctrl"); Utils.Save( Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "CodeGenerate\\Code\\Controller", $"{Utils.ToCamelName(tablename) + "Controller"}.cs") , ctrl_result); builder.Append(ctrl_result); #endregion return builder.ToString(); } public class ColumnInfo { public string table_name { get; set; } public string column_name { get; set; } public int? ordinal_position { get; set; } public string is_nullable { get; set; } public string data_type { get; set; } public int? character_maximum_length { get; set; } public string column_key { get; set; } public string column_comment { get; set; } } public class TableInfo { public string table_name { get; set; } public string table_comment { get; set; } } } }
-----------------------------------
Util.cs
-----------------------------------
using System.IO; using System.Text; namespace ConsoleApp1 { public class Utils { /// <summary> /// 類型轉化 /// </summary> /// <param name="dbType"></param> /// <returns></returns> public static string GetCsType(string dbType) { string csType = ""; switch (dbType.ToLower()) { case "varchar": case "varchar2": case "nvarchar": case "nvarchar2": case "char": case "nchar": case "text": case "longtext": case "string": csType = "string"; break; case "date": case "datetime": case "smalldatetime": case "timestamp": csType = "DateTime"; break; case "int": case "number": case "smallint": case "integer": csType = "int"; break; case "bigint": csType = "Int64"; break; case "float": case "numeric": case "decimal": case "money": case "smallmoney": case "real": case "double": csType = "decimal"; break; case "tinyint": case "bit": csType = "bool"; break; case "binary": case "varbinary": case "image": case "raw": case "long": case "long raw": case "blob": case "bfile": csType = "byte[]"; break; case "uniqueidentifier": csType = "Guid"; break; case "xml": case "json": csType = "string"; break; default: csType = "object"; break; } return csType; } /// <summary> /// 保存 /// </summary> /// <param name="path"></param> /// <param name="content"></param> /// <returns></returns> public static string Save(string path, string content) { string dir = path.Substring(0, path.LastIndexOf("\\") + 1); if (!System.IO.Directory.Exists(dir)) System.IO.Directory.CreateDirectory(dir); File.WriteAllText(path, content); return path; } private static System.Text.RegularExpressions.Regex regSpace = new System.Text.RegularExpressions.Regex(@"\s"); /// <summary> /// 去掉空格 /// </summary> /// <param name="value"></param> /// <returns></returns> public static string ReplaceSpace(string value) { if (string.IsNullOrEmpty(value)) return string.Empty; char firstChar = value[0]; if (firstChar >= 48 && firstChar <= 57) { value = "_" + value; } return regSpace.Replace(value.Trim(), " "); } /// <summary> /// 首字母大寫 /// </summary> /// <param name="value"></param> /// <returns></returns> public static string ToUpperFirstword(string value) { if (string.IsNullOrEmpty(value)) return string.Empty; return value.Substring(0, 1).ToUpper() + value.Substring(1); } /** * 將下划線大寫方式命名的字符串轉換為駝峰式。如果轉換前的下划線大寫方式命名的字符串為空,則返回空字符串。</br> * 例如:HELLO_WORLD->HelloWorld * @param name 轉換前的下划線大寫方式命名的字符串 * @return 轉換后的駝峰式命名的字符串 */ /// <summary> /// 轉換為駝峰命名 /// </summary> /// <param name="name"></param> /// <returns></returns> public static string ToCamelName(string name) { StringBuilder result = new StringBuilder(); // 快速檢查 if (name == null || string.IsNullOrEmpty(name)) { // 沒必要轉換 return ""; } else if (!name.Contains("_")) { // 不含下划線,僅將首字母大寫 return name.Substring(0, 1).ToUpper() + name.Substring(1).ToLower(); } // 用下划線將原始字符串分割 string[] camels = name.Split('_'); foreach (string camel in camels) { // 跳過原始字符串中開頭、結尾的下換線或雙重下划線 if (string.IsNullOrEmpty(camel)) { continue; } // 處理真正的駝峰片段 //if (result.Length == 0) //{ // // 第一個駝峰片段,全部字母都小寫 // result.Append(camel.ToLower()); //} //else //{ // 其他的駝峰片段,首字母大寫 result.Append(camel.Substring(0, 1).ToUpper()); result.Append(camel.Substring(1).ToLower()); //} } return result.ToString(); } } }