通过调用指定目录下的所有模板,逐一按照数据表生成独立的代码文件。支持多模板调用、支持所有数据表生成或批量指定多个生成、支持自动的文件目录结构、支持代码文件格式化命名等。

背景:最近一个新项目一高兴选了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是否手动选择了数据表,如果没有则为所有表。

  准备工作做好之后,就是遍历数据表、遍历模板,生成对应的代码文件了。具体情况已在代码中注释。

CodeSmith 二、多模板按目录树批量自动生成代码的更多相关文章

  1. 组件化框架设计之apt编译时期自动生成代码&动态类加载(二)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将继续从以下两个内容来介绍组件化框架设计: apt编译时 ...

  2. GZFramwork数据库层《二》单据表增删改查(自动生成单据号码)

    运行效果: 使用代码生成器(GZCodeGenerate)生成tb_EmpLeave的Model 生成器源代码下载地址: https://github.com/GarsonZhang/GZCodeGe ...

  3. (二十二)SpringBoot之使用mybatis generator自动生成bean、mapper、mapper xml

    一.下载mybatis generator插件 二.生成generatorConfig.xml new一个generatorConfig.xml 三.修改generatorConfig.xml 里面的 ...

  4. IT轮子系列(二)——mvc API 说明文档的自动生成——Swagger的使用(一)

    这篇文章主要介绍如何使用Swashbuckle插件在VS 2013中自动生成MVC API项目的说明文档.为了更好说明的swagger生成,我们从新建一个空API项目开始. 第一步.新建mvc api ...

  5. (二)一个很好用的自动生成工具——mybatis generator

    mybatis generator-自动生成代码 准备材料: 一个文件夹,一个数据库的驱动包,mybatis-generator-core-1.3.5.jar,一条生成语句 如图:(我用的是derby ...

  6. CodeSmith自动生成代码使用

    官网地址:http://www.codesmithtools.com/ CodeSmith开发系列资料总结 http://terrylee.cnblogs.com/archive/2005/12/28 ...

  7. Java IDEA 根据mybatis-generator-core自动生成代码支持sqlserver获取备注(二)

    mybatis generator代码生成虽然好用,但是好像不支持sqlserver获取备注信息,这里我主要分享mybatis generator改写后支持sqlserver获取备注信息,mysql以 ...

  8. 第十五节:Expression表达式目录树(与委托的区别、自行拼接、总结几类实例间的拷贝)

    一. 基本介绍 回忆: 最早接触到表达式目录树(Expression)可能要追溯到几年前使用EF早期的时候,发现where方法里的参数是Expression<Func<T,bool> ...

  9. 在Asp.net core使用配置Json创建动态目录树

    一.前言 使用动态目录树可以使左边栏中的目录更加灵活,本文介绍如何将目录保存在json配置文件中,再读取出来经过处理后生成目录树. 二.数据结构 1. TreeMenuNode类名 将TreeMenu ...

随机推荐

  1. SpringBoot 项目在静态工具类中注入 RedisTemplate

    静态属性不能直接注入,可以通过其set方法进行注入.(注意生成的set方法需要去掉static). 在工具类里直接注入RedisTemplate,两种方法: (1)使用@Autowired priva ...

  2. [Swift]LeetCode1036.逃离大迷宫 | Escape a Large Maze

    In a 1 million by 1 million grid, the coordinates of each grid square are (x, y) with 0 <= x, y & ...

  3. AI - TensorFlow - 可视化工具TensorBoard

    TensorBoard TensorFlow自带的可视化工具,能够以直观的流程图的方式,清楚展示出整个神经网络的结构和框架,便于理解模型和发现问题. 可视化学习:https://www.tensorf ...

  4. 【Git之旅】2.Git对象

    1.块(blob)对象 (1)文件的每一个版本表示为一个块 (2)二进制大对象(binary large object)的缩写,是计算机领域的常用术语,用来指代某些可以包含任意数据的变量或文件,同时其 ...

  5. 从ASP.NET Core2.2到3.0你可能会遇到这些问题

    趁着假期的时间所以想重新学习下微软的官方文档来巩固下基础知识.我们都知道微软目前已经发布了.NET Core3.0的第三个预览版,同时我家里的电脑也安装了vs2019.So,就用vs2019+.NET ...

  6. ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)

    早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安 ...

  7. 阿里云Ubuntu下安装、配置权限和导入本地mongodb

    ---恢复内容开始--- 第一部分:首先先在Ubuntu下安装好mongodb,步骤如下: 首先我们需要借助远程管理工具链接到阿里云上的ubuntu系统,接着进行如下操作 一.导出软件源的公钥 sud ...

  8. 接口自动化:HttpClient + TestNG + Java(二) - 第一个接口测试:get请求

    在上一篇中,我们搭建好了HttpClient + TestNG + Java的自动化接口测试环境,这一篇我们就赶紧开始编写我们的第一个接口测试用例. 本篇会对问题解决的思路进行更详尽的阐述. 2.1 ...

  9. Virtual Box虚拟机Ubuntu系统安装及基本配置

    Linux简介 什么是 Linux? Linux:世界上不仅只有一个 Windows 操作系统,还有 Linux.mac.Unix 等操作系统.桌面操作系统下 Windows 是霸主,而 Linux ...

  10. 【网摘】EasyUI常用控件禁用启用方法

    1.validatebox可以用的用法:前两种适用于单个的validatebox; 第三种应用于整个form里面的输入框; <1>.$("#id").attr(&quo ...