从壹开始前后端分离 [.netCore 填坑 ] 三十二║ 四种方法快速实现项目的半自动化搭建
返回框架目录 更快检索
本文梯子
缘起
一、动软代码生成器搭建整体项目框架
1、安装与使用
二、通过 VSTO 编写 Excel 来搭建整体项目...
1、什么是VSTO?
2、如何新建一个 VSTO 项目
三、通过 T4 模板搭建整体项目框架
1、什么是 T4 模板
2、在项目中通过T4实现数据库生成实体类
3、实现整个系统框架模板
四、SqlSugar等ORM框架来实现 DbFir...
五、结语
六、Github代码
正文
缘起
哈喽大家周二好呀,这个国庆过的真是懒洋洋呀,不知道大家的学习动力咋样了,刚一上班本人手中的项目也增加了,但是还是要抽出时间学习哒,为了不让老板大大天天催,所以更新会慢点儿 [ 哭笑 ] :bowtie:,不过在我的推荐下,公司下一个项目要我负责前后端分离,终于可以将这些派上用场了,中间的坑也会在以后的文章中,慢慢补充出来。
这几天简单想了想,还没有想好要开什么系列,就想到QQ群里有小伙伴问的较多的一些问题以及前边系列文章中的提到的,但是没有深入讲到的,再填一下坑,这样才是完整的嘛,大家要是看到之前的有任何不清楚的,或者想扩展的,可以在群里说一下,或者留言,我都会说到的。今天呢,就说说如果半自动化搭建项目,这个坑来自于之前的项目搭建文章《框架之六 || API项目整体搭建 6.1 仓储模式》的伏笔之一 —— 如何使用 T4 模板搭建项目。当然,我们不仅是简单说说实体类的创建,也会横向和纵向的讨论下,一个项目如何通过代码实现半自动化搭建。
说到这里大家应该已经明白了这篇文章的写作意图,就是搭建项目的问题,相信大家已经开发了几年了,都有自己的一套行之有效的办法或者是经验,当然这里就不说付费的了,付费的框架何其多,比如迪西客,普元或者力软等等,这都是好用的功能强大的付费框架,既然说技术,就不说付费的,咱们自己写,这里简单概括下今天要说到的:
0、手动粘贴复制 —— 可能现在还有小伙伴在用这个办法,效率是真的很低,虽然我偶尔也用哈哈,这里就不说了
1、动软代码生成器 —— 这个我入门的时候使用的神器,用了好久
2、通过 VSTO 来编写 Excel ,实现每一层的代码设计 —— 我没用过,但是见过,一个不错的思路
3、T4 模板 —— 这个是我这两年遇到的又一个神器,也是一直使用的,强烈推荐的
4、SqlSuagr(ORM)—— 自封装的一套逻辑,当然其他ORM也有,比如EF就很好
今天咱们这几个方法都会说到,主要还是说一下通过 T4 模板,来把我们的整体框架半自动化起来。最终的效果截图是这样的:
框架截图
一、动软代码生成器搭建整体项目框架
相信很多的小伙伴应该使用过这个工具,还是很不错的,我也是用了有一段时间,虽然很小,但是功能确实很丰富,无论是生成实体类,还是生成简单三层,还是工厂模式等等,都可以使用,不仅支持单个表文件的操作,也支持整个数据库的批量生成,这里具体的不做叙述,因为不是本篇文章的重点,这里简单的说下使用方法以及效果图:
1、安装与使用
地址:http://www.maticsoft.com/download.aspx
安装还是很简单的,就是普通的 next ,想用的可以试试,这里就不做叙述了。
安装成功后,我们可以看到,通过连接相应的服务器,找到适当的数据库,就可以操作了,主要还是通过一套 cmt 模板来生成对应的 .cs 类文件,这些模板我们可以使用系统自带的(比如工厂模式模板),也可以自定义编辑,以满足我们不同项目的具体需求,我这里就演示下,如何把我的博客数据库(还是咱们一直用的这个数据库),生成简单工程框架。
经过短暂的等待后,我们的全部框架就这么出来了
当然这些后缀名等都可以配置,这里就不细说了,咱们随便看一下数据访问层的内容:
View Code
提示:如果你不想下载改软件,又想看看具体的代码,我已经提交到咱们的git 了,在wwwroot 文件夹中,大家可以看看
截图
打开看一下,基本的 CURD 方法都有,也有一些存储过程的调用等,而且可以自定义扩展,不得不说是一个神器,如果要开发 ADO.NET 多层,这个方法也不失为一个好的方案。
优点大家都看到了,快速,内容简洁丰富,各种存储过程分页方法很方便,不言而喻;
但是缺点也是有的,最大的就是不能像其他ORM框架那样,实现 Code First ,只能单纯的讲数据库信息提取出来;而且在编辑模板方面也没有 T4 那么容易操作,修改模板代码不是很方便,学习的难度稍微大了一些。
总结:如果不想用 T4 模板手动写模板代码,又不想引入框架,只想用 ADO.NET 搭建多层框架,动软代码生成器是一个不错的选择。
二、通过 VSTO 编写 Excel 来搭建整体项目框架
1、什么是VSTO?
VSTO(Visual Studio Tools For Office)就像名字一样,是Visual Studio开发Office的工具集。只是一套工具,用于简化.NET的Office开发。能够生成com组件或者标准dll的都能开发Office,比如c/c++,VB6,Delphi等等。原生.NET当然也可以。微软觉得.net开发Office不够方便,VSTO便诞生了。
1.决定要用.NET开发Office
2.在所有.NET开发Office的途径(原始,各种工具)中,选择了VSTO
2、如何新建一个 VSTO 项目
网上有一个栗子,大家可以参看着自己玩一玩:https://www.cnblogs.com/crhdyl/p/5289307.html。 对于这个方法,大家自己玩一玩就好了,这里就不说具体的教程了,毕竟不是本文重点。
QQ群里有一个小伙伴大神,他通过 VSTO 来写的一个框架,其实就是通过命令来将固定的格式进行输出,这里盗用一下他的图,应该还好吧,因为不知道他的博客园账号,就先不@他了,个人感觉这个还是很不错的,看着很溜
这个方法我现在也在学,不过只是做一个知识扩展来用,好处是,我们自己做一个Excel 工具后,走到哪里都可以使用,还很方便,自己随便自定义,不用受项目或者数据库的环境影响,特别是做展示的时候,很直观,比如开项目研讨会的时候,几个人讨论数据库表结构呀,生成的方法呀,总不能一个个软件都打开吧;
但是也有一些问题,毕竟局限性有些强,比如好像不能直接操作数据库,在大数据结构中,效率不高,而且不能直接生成文件,需要拷贝操作等;
通过上边两个栗子可以看出来,一个是连接数据库快捷,文件生成方便;一个自定义逻辑性强,展示直观,那有没有办法可以将两个优点结合起来呢,没错,就是T4模板了,耐心看完下边的讲解,你会发现很强大。
三、通过 T4 模板搭建整体项目框架
1、什么是 T4 模板
T4 (Text Template Transformation Toolkit) 是微软官方在 VisualStudio 2008+ 中开始使用的代码生成引擎。在 Visual Studio 中,“T4 文本模板”是由一些文本块和控制逻辑组成的混合模板,它可以生成文本文件。 在 Visual C# 或 Visual Basic 中,控制逻辑编写为程序代码的片段。生成的文件可以是任何类型的文本,例如网页、资源文件或任何语言的程序源代码。现在的VS中只要与代码生成相关的场景基本上都能找T4的身影,比如MVC的视图模板,Entity Framwork的DataContext模板等等。
2、在项目中通过T4实现数据库生成实体类
这里就不具体讲解 T4 语法了,大家可以自行学习,其实很简单,主要还是 C# 代码,下边你看过之后就能懂了,咱们首先先实现之前留下的一个伏笔 —— 将我们的数据库表利用T4 模板生成实体类,也就是 DbFirst。
1、首先在我们的项目中,新建一个类库 Blog.Core.FrameWork
2、在该类库下,新建文件夹 Blog.Core.FrameWork.Entity,用于单独存放我们的模板以及生成的实体类文件
3、在类库的根目录新建 ModelAuto.ttinclude 模板文件,用来控制我们的文件生成配置
可以直接新建一个文本文档,然后重命名即可
提示:初始状态下,代码不是高亮的,大家可以安装插件:下载地址,不过个人感觉并不是很好用。
复制代码
//引入命名空间
<#@ assembly name="System.Core"#>
<#@ assembly name="EnvDTE"#>
<#@ import namespace="System.Collections.Generic"#>
<#@ import namespace="System.IO"#>
<#@ import namespace="System.Text"#>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating"#>
<#+
//定义管理者 manager 实体类
class Manager
{
//定义一个 block 块,主要是应用在批量生产中
public struct Block {
public String Name;
public int Start, Length;
}
public List blocks = new List();
public Block currentBlock;
public Block footerBlock = new Block();
public Block headerBlock = new Block();
public ITextTemplatingEngineHost host;
public ManagementStrategy strategy;
public StringBuilder template;
public String OutputPath { get; set; }
//构造函数,包含 host主机,模板,输出路径,创建管理策略
public Manager(ITextTemplatingEngineHost host, StringBuilder template, bool commonHeader) {
this.host = host;
this.template = template;
OutputPath = String.Empty;
strategy = ManagementStrategy.Create(host);
}
//开辟一个 block 块
public void StartBlock(String name) {
currentBlock = new Block { Name = name, Start = template.Length };
}
public void StartFooter() {
footerBlock.Start = template.Length;
}
public void EndFooter() {
footerBlock.Length = template.Length - footerBlock.Start;
}
public void StartHeader() {
headerBlock.Start = template.Length;
}
public void EndHeader() {
headerBlock.Length = template.Length - headerBlock.Start;
}
public void EndBlock() {
currentBlock.Length = template.Length - currentBlock.Start;
blocks.Add(currentBlock);
}
//定义进程,用来将所有的 blocks 块执行出来
public void Process(bool split) {
String header = template.ToString(headerBlock.Start, headerBlock.Length);
String footer = template.ToString(footerBlock.Start, footerBlock.Length);
blocks.Reverse();
foreach(Block block in blocks) {//遍历
//输出文件
String fileName = Path.Combine(OutputPath, block.Name);
if (split) {
String content = header + template.ToString(block.Start, block.Length) + footer;
strategy.CreateFile(fileName, content);
template.Remove(block.Start, block.Length);
} else {
strategy.DeleteFile(fileName);
}
}
}
}
//定义管理策略类
class ManagementStrategy
{
internal static ManagementStrategy Create(ITextTemplatingEngineHost host) {
return (host is IServiceProvider) ? new VSManagementStrategy(host) : new ManagementStrategy(host);
}
internal ManagementStrategy(ITextTemplatingEngineHost host) { }
internal virtual void CreateFile(String fileName, String content) {
File.WriteAllText(fileName, content);
}
internal virtual void DeleteFile(String fileName) {
if (File.Exists(fileName))
File.Delete(fileName);
}
}
class VSManagementStrategy : ManagementStrategy
{
private EnvDTE.ProjectItem templateProjectItem;
internal VSManagementStrategy(ITextTemplatingEngineHost host) : base(host) {
IServiceProvider hostServiceProvider = (IServiceProvider)host;
if (hostServiceProvider == null)
throw new ArgumentNullException("Could not obtain hostServiceProvider");
EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE));
if (dte == null)
throw new ArgumentNullException("Could not obtain DTE from host");
templateProjectItem = dte.Solution.FindProjectItem(host.TemplateFile);
}
//创建文件
internal override void CreateFile(String fileName, String content) {
base.CreateFile(fileName, content);
((EventHandler)delegate { templateProjectItem.ProjectItems.AddFromFile(fileName); }).BeginInvoke(null, null, null, null);
}
//删除文件
internal override void DeleteFile(String fileName) {
((EventHandler)delegate { FindAndDeleteFile(fileName); }).BeginInvoke(null, null, null, null);
}
//根据文件名删除文件
private void FindAndDeleteFile(String fileName) {
foreach(EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems) {
if (projectItem.get_FileNames(0) == fileName) {
projectItem.Delete();
return;
}
}
}
}#>
复制代码
4、还是在类库根目录下新建 DbHelper.ttinclude 模板,主要是数据库操作类
View Code
具体的代码就不细讲了,直接拷贝,或者下载我写好的代码即可。再次说明下,本文不会对 T4 语法继续深入研究。
5、实现生成全部实体类的模型设计,在Blog.Core.FrameWork.Entity文件夹下,新建 Blog.Core.FrameWork.Entity.tt 模板
填写代码
复制代码
//如果要获取主机信息,记得把 hostspecific 设置成true
<#@ template debug="false" hostspecific="True" language="C#" #>
<#@ output extension=".cs" #>
//导入命名空间组件
<#@ assembly name="System.Data" #>
<#@ assembly name="System.xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Data" #>
<#@ assembly name="System.Core.dll" #>
<#@ assembly name="System.Data.DataSetExtensions.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
//引入我们的公共模板文件
<#@ include file="$(ProjectDir)DbHelper.ttinclude" #>
<#@ include file="$(ProjectDir)ModelAuto.ttinclude" #>
//定义我们的输出文件夹
<#
var OutputPath1 = Path.GetDirectoryName(Host.TemplateFile)+"\\work";
if (!Directory.Exists(OutputPath1))
{
Directory.CreateDirectory(OutputPath1);
}
var manager = new Manager(Host, GenerationEnvironment, true) { OutputPath = OutputPath1 };
#>
//--------------------------------------------------------------------
// 此代码由T4模板自动生成
// 老张的哲学 生成时间 <#=DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")#>
// 注意更新后会改变相应代码。
//--------------------------------------------------------------------
<#
var tableName=config.TableName;//获取config配置中的表名,为单一生产使用
#>
<#
if(tableName!=""){//如果表名有值,表示是生成单一文件
#>
//引用命名空间
using System;
namespace Blog.Core.FrameWork.Entity
{
///
/// <#=tableName#>
///
public class <#=tableName#>//可以在这里加上基类等
{
//将全部字段遍历出来
<# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, config.TableName)){#>
public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; }
<#}#>
}
}
//如果为空,表示要将整个数据库都生成出来
<#
} else{
#>
//连接数据库,打开 connect 连接
<#
SqlConnection conn = new SqlConnection(config.ConnectionString);
conn.Open();
System.Data.DataTable schema = conn.GetSchema("TABLES");
#>
//遍历全部数据库表
<#
foreach(System.Data.DataRow row in schema.Rows)
{ #>
//开始启动block块,参数是实体类文件名
<#
manager.StartBlock(row["TABLE_NAME"]+".cs");
#>
//----------<#=row["TABLE_NAME"].ToString()#>开始----------
using System;
namespace Blog.Core.FrameWork.Entity
{
///
/// <#=tableName#>
///
public class <#=row["TABLE_NAME"].ToString()#>//可以在这里加上基类等
{
//将该表下的字段都遍历出来,可以自定义获取数据描述等信息
<# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, row["TABLE_NAME"].ToString() )){ #>
public <#= column.CSharpType#> <# if(column.CommonType.IsValueType && column.IsNullable){#> ?<#}#> <#=column.ColumnName #> { get; set; }
<#}#>
}
}
//----------<#=row["TABLE_NAME"].ToString()#>结束----------
<#
manager.EndBlock();
}
manager.Process(true);
}
#>
复制代码
这里我写的比较凌乱,大概就是这个逻辑,其实和 C# 特别相像,主要简单的看一看,就都会明白,这个时候我们保存文件 ctrl+S,如果你连接数据库正确的话,会发现已经生成了全部实体类文件。
随便打开一个实体类,就可以发现,和我们自己写的是一样的:是不是很方便!
复制代码
//----------BlogArticle开始----------
using System;
namespace Blog.Core.FrameWork.Entity
{
///
/// BlogArticle
///
public class BlogArticle//可以在这里加上基类等
{
//将该表下的字段都遍历出来,可以自定义获取数据描述等信息
public int bID { get; set; }
public string bsubmitter { get; set; }
public string btitle { get; set; }
public string bcategory { get; set; }
public string bcontent { get; set; }
public int btraffic { get; set; }
public int bcommentNum { get; set; }
public DateTime bUpdateTime { get; set; }
public DateTime bCreateTime { get; set; }
public string bRemark { get; set; }
}
}
//----------BlogArticle结束----------
复制代码
这个时候你会问,这个既然这么好,能全部生成其他层么?没错,答案当然是肯定的!
3、实现整个系统框架模板
因为篇幅的问题,这里就不把代码粘贴出来了,大家自己去Github 上获取即可,最终的效果是酱紫的:
是不是很神器!整个系统框架就在一瞬间就加载出来了,大家下载好后,只需要 ctrl + S 保存一下 tt 模板文件,就能全部生成,只需要把精力放到 Base 基类/基接口即可,以后数据库表结构无论如何变化都不怕!
四、SqlSugar等ORM框架来实现 DbFirst
总结来说,其实一般的 ORM 框架,都是集成的 T4模板,EF是如此,咱们的SqlSugar 也是这样,已经封装好了相应的逻辑代码:
复制代码
using (SqlSugarClient db =SqlSugarInstance.GetInstance())
{
try
{
// db.CodeFirst.InitTables(typeof(实体类model));
db.DbFirst.Where("数据库表名").CreateClassFile("D:\\Demo\\2.cs");//生成文件的·地址
}
catch (Exception ex)
{
}
}
复制代码
还记得咱们 Repisitory 层中的 DbContext.cs 文件么,里边我已经封装好了,直接在 BaseRepository.cs 或者自己写的任何文件中调用就行,只不过这里仅仅是 Model 层的。这里就不多说了。
五、结语
今天也是在忙碌中,抽出时间写了写,主要是给大家分享了下,如何快速的半自动化的实现项目搭建,也算是一个小技巧了,重点说明了下 T4模板搭建全部层文件,个人感觉还是可行的,主要是灵活性很强,需要的小伙伴可以好好的研究一下,继续奋斗中!!!
六、Github代码
https://github.com/anjoy8/Blog.Corehttps://www.cnblogs.com/laozhang-is-phi/p/9757999.html