C#实现代码生成器
最近在用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(); } } }