CodeSmith 二、多模板按目录树批量自动生成代码

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

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

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

原文地址:https://www.cnblogs.com/FlyLolo/p/CodeSmith_2.html

时间: 2024-10-07 19:34:19

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

Python使用模板自动生成代码

整体思想: 完全按照自己的想法来写的,首先写模板文件,然后打开模板文件,对模板进行字符串格式化处理,最后再将格式化后的字符串保存到新的文件里面.如有更好的想法,欢迎交流. 将相似度很高的代码写模板文件(widget_template.txt): # -*- coding: UTF-8 -*- #!/usr/bin/env python #-------------------------------------------------------------------------------

CodeSmith自动生成代码使用

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

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

运行效果: 使用代码生成器(GZCodeGenerate)生成tb_EmpLeave的Model 生成器源代码下载地址: https://github.com/GarsonZhang/GZCodeGenerate/ 生成方式见上一节: GZFramwork数据库层<一>普通表增删改查     新增一个自定义控件:ucTableUnitDocNo   后台代码同上一节ucTableUnit除了实例化bllBusiness不一样外其他都一样(红色背景标注) using System; using

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

一.前言 使用动态目录树可以使左边栏中的目录更加灵活,本文介绍如何将目录保存在json配置文件中,再读取出来经过处理后生成目录树. 二.数据结构 1. TreeMenuNode类名 将TreeMenuNode类设置成与json格式相对应,注意Children应为List类型.目录的内容包括MenuName,Action,Controller,Icon public class TreeMenuNode2 { public int MenuNumber { get; set; } public s

利用jQuery无插件创建可扩展目录树

这是一个简单.轻量级的,基于jQuery的目录树.纯html代码. <html> <head> </head> <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>   <script> $( document ).ready( function( ) {     $( '.t

使用 Velocity 模板引擎快速生成代码

原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-velocity1/ Velocity 是一个基于 Java 的模板引擎,它允许任何人仅仅简单的使用模板语言来引用由 Java 代码定义的对象,从而实现界面和 Java 代码的分离,使得界面设计人员可以和 Java 程序开发人员同步开发一个遵循 MVC 架构的 web 站点.但是在实际应用过程中,Velocity 又不仅仅被用在了 MVC 的架构中. Velocity 模板引擎介绍 在现今的软

[goa]golang微服务框架学习(二)-- 代码自动生成

之前用过go语言的反射来做一些代码生成,参考这篇. 但是这种方式,入侵太强,需要执行对应的申明调用, 所以对GOA框架的自动生成非常感兴趣,于是仔细研究了一下,发现用的比较巧妙, 这里先卖个关子,先看看生成的代码目录结构. 这里使用adder的desgin文件来生成: package design import ( . "github.com/goadesign/goa/design" . "github.com/goadesign/goa/design/apidsl&quo

让博客园博客自动生成章节目录索引

一个好的博文除了博文的质量要好以外,好的组织结构也能让读者阅读的更加舒服与方便,我看园子里面有一些园友的博文都是分章节的,并且在博文的前面都带有章节的目录索引,点击索引之后会跳转到相应的章节阅读,并且还可以回到目录顶端,其中 Fish Li 的博文就是这种组织,当然这种结构如果是在写博文的时候人工设置那是非常麻烦的,无疑是增加了写作人的工作量.如果能自动生成章节索引岂不是节省了一大堆工作量.本来想通过FireBug看看Fish Li源码是怎么实现的,但是好像js是加密过的.那我就自己动手了,其实

[转]黄聪:如何使用CodeSmith批量生成代码

本文转自:http://www.cnblogs.com/huangcong/archive/2010/06/14/1758201.html 在上一篇我们已经用PowerDesigner创建好了需要的测试数据库,下面就可以开始用它完成批量代码生成的工作啦. 下面我会一步步的解释如何用CodeSmith实现预期的结果的,事先声明一下,在此只做一个简单的Demo,并不详细的讲解CodeSmith各个强大的功能,有兴趣的朋友可以打开CodeSmith的帮助文档了解.我只做个抛砖引玉,希望能激起大家更多思