通过调用指定目录下的所有模板,逐一按照数据表生成独立的代码文件。支持多模板调用、支持所有数据表生成或批量指定多个生成、支持自动的文件目录结构、支持代码文件格式化命名等。
背景:最近一个新项目一高兴选了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 98 99 <% this.Generate(); %>
最上面是各种属性设置:
1. NameSpace: 用于设置项目统一的命名空间前缀。
2. SourceDatabase:可以弹出的对话框中选择已经配置好的数据库。
3. SourceTables:批量选择数据表,可以按住ctrl或shift多选。
4. TemplateDirectory:模板所在目录,支持树状目录结构。
5. ExceptPrefix:排除模板前缀,前缀为这样的模板不会被获取。
6. OutputDirectory:生成文件存储目录,其子目录结构会按照模板目录结构。
此模板文件的入口是Generate(),它首先会调用GetTemplates方法读取属性TemplateDirectory指定的目录下的所有模板,并记录各个模板所在的目录结构。然后判断属性SourceTables是否手动选择了数据表,如果没有则为所有表。
准备工作做好之后,就是遍历数据表、遍历模板,生成对应的代码文件了。具体情况已在代码中注释。