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

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

三、创建模板

  首先创建一个最简单的模板,用于生成实体类,在右上角的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,会弹出对话框让选择一个数据表,选择后点击生成按钮,会生成类似如下代码:

14.png

 我要的肯定不是每次选择一个表,也不想一个个生成之后复制粘贴到项目中去。而且我也不是只需要这样的一个模板,我要自动生成的有好多。

四、制作用于批量调用的模板

  首先仿照上例新建了几个模板,例如生成Controller的、ViewModel的,目录结构如下:

15.png

 这些都是具体的“子模板”,然后按照上面的需求新建了一个名为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是否手动选择了数据表,如果没有则为所有表。


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


目录
相关文章
|
Web App开发 编解码 Android开发
2023年音视频开发知识技术合集(基础入门到高级进阶)
2023年音视频开发知识技术合集(基础入门到高级进阶)
|
11月前
|
JSON 数据格式 C++
cpp struct json相互转换
使用 `nlohmann/json`库,可以简便地在C++中实现结构体与JSON之间的相互转换。通过定义序列化和反序列化函数,可以处理简单和复杂的结构体类型。这种方法不仅提高了代码的可读性和维护性,还增强了数据交换的灵活性。
608 26
|
开发框架 前端开发 .NET
C# Newtonsoft.Json.Formatting DateTime 日期格式化
C# Newtonsoft.Json.Formatting DateTime 日期格式化
338 0
|
SQL 关系型数据库 MySQL
【Mysql】MYSQL参数max_allowed_packet 介绍
【Mysql】MYSQL参数max_allowed_packet 介绍
1455 0
|
IDE Java 编译器
开发 Java 程序一定要安装 JDK 吗
开发Java程序通常需要安装JDK(Java Development Kit),因为它包含了编译、运行和调试Java程序所需的各种工具和环境。不过,某些集成开发环境(IDE)可能内置了JDK,或可使用在线Java编辑器,无需单独安装。
588 2
|
运维 Kubernetes Docker
微服务的成本效益分析
【8月更文第29天】随着微服务架构的流行,越来越多的企业开始考虑采用这一架构模式来构建他们的应用程序和服务。然而,迁移到微服务并非没有代价。本文旨在评估采用微服务架构所带来的成本增加与收益,并探讨如何优化资源使用,以最大化成本效益比。
987 2
|
人工智能 C++
【Azure Developer】上手 The Best AI Code "Cursor" : 仅仅7次对话,制作个人页面原型,效果让人惊叹!
本文介绍了使用 Cursor 这款 AI 辅助编程工具的步骤与体验。通过下载安装 Cursor 并使用 GitHub 账号登录,你可以创建 HTML 文件并借助 AI 自动生成代码。文章详细描述了如何逐步优化生成的内容,包括调整布局、增加样式及响应式设计等。此外,还展示了通过多次迭代改进后的最终效果,并提供了生成的 HTML 模板代码,便于读者直接使用或进一步修改。
504 3
|
机器学习/深度学习 人工智能 供应链
AI在各行业的具体应用与未来展望
人工智能(Artificial Intelligence, AI)作为一项颠覆性技术,正在逐步改变我们的生活和工作方式。从语音助手到自动驾驶汽车,AI的应用已经深入到各个领域。本文将详细探讨AI在不同行业中的具体应用,以及未来可能的发展方向。
3633 6
|
存储 NoSQL Ubuntu
在Ubuntu 16.04上安装和配置Redis的方法
在Ubuntu 16.04上安装和配置Redis的方法
328 0