NET Core项目模板
打造自己的.NET Core项目模板
https://www.cnblogs.com/catcher1994/p/10061470.html
前言
每个人都有自己习惯的项目结构,有人的喜欢在项目里面建解决方案文件夹;有的人喜欢传统的三层命名;有的人喜欢单一,简单的项目一个csproj就搞定。。
反正就是萝卜青菜,各有所爱。
可能不同的公司对这些会有特定的要求,也可能会随开发自己的想法去实践。
那么,问题就来了。如果有一个新项目,你会怎么去创建?
可能比较多的方式会是下面三种:
简单粗暴型,打开VS就是右键添加,然后引入一堆包,每个项目添加引用。
脚本型,基于dotnet cli,创建解决方案,创建项目,添加包,添加项目引用。
高大上型,VS项目模板,直接集成到VS上面了。
以前我也是基于dotnet cli写好了sh或ps的脚本,然后用这些脚本来生成新项目。
但是呢,这三种方式,始终都有不尽人意的地方。
因为建好的都是空模板,还要做一堆复杂的操作才可以让项目“正常”的跑起来。比如,这个公共类要抄过来,那个公共类要抄过来。。。这不是明摆着浪费时间嘛。。。
下面介绍一个小办法来帮大家省点时间。
基于dotnet cli创建自己的项目模板,也就是大家常说的脚手架。
dotnet cli项目模板预热
开始正题之前,我们先看一下dotnet cli自带的一些模板。
可以看到种类还是很多的,由于工作大部分时间都是在写WebAPI,所以这里就用WebAPI来写个简单的模板。
下面我们就基于dotnet cli写一个自己的模板。
编写自己的模板
既然是模板,就肯定会有一个样例项目。
下面我们建一个样例项目,大致成这样,大家完全可以按照自己习惯来。
这其实就是一个普通的项目,里面添加了NLog,Swagger,Dapper等组件,各个项目的引用关系是建好的。
该有的公共类,里面也都包含了,好比宇内分享的那个WebHostBuilderJexusExtensions。
下面是这个模板跑起来的效果。
就是一个简单的Swagger页面。
现在样例已经有了,要怎么把这个样例变成一个模板呢?
答案就是template.json!
在样例的根目录创建一个文件夹.template.config,同时在这个文件夹下面创建template.json。
示例如下:
{
"author": "Catcher Wong", //必须
"classifications": [ "Web/WebAPI" ], //必须,这个对应模板的Tags
"name": "TplDemo", //必须,这个对应模板的Templates
"identity": "TplDemoTemplate", //可选,模板的唯一名称
"shortName": "tpl", //必须,这个对应模板的Short Name
"tags": {
"language": "C#" ,
"type":"project"
},
"sourceName": "TplDemo",  // 可选,要替换的名字
"preferNameDirectory": true  // 可选,添加目录
}
在这里,有几个比较重要的东西,一个是shortName,一个是sourceName。
shortName,简写,偷懒必备,好比能写 -h 就绝对不写 --help
sourceName,这是个可选的字段,它的值会替换指定的项目名,正常是把项目名赋值在这里。如果不指定,创建的项目就和样例项目保持一致。
在写完template.json之后,还需要安装一下这个模板到我们的cli中。
使用 dotnet new -i进行模板的安装。
下面是安装示例。
dotnet new -i ./content/TplDemo
这里要注意的是,与.template.config文件夹同级的目录,都会被打包进模板中。
在执行安装命令之后,就可以看到我们的模板已经安装好了。
这个时候已经迫不及待的想来试试这个模板了。
先来看看这个模板的帮助信息。
dotnet new tpl -h
因为我们目前还没有设置参数,所以这里显示的是还没有参数。
下面来创建一个项目试试。
从创建一个项目,到运行起来,很简单,效果也是我们预期的。
下面来看看,新建的这个HelloTpl这个项目的目录结构和我们的模板是否一样。
可以看到,除了名字,其他的内容都是一样的。
是不是感觉又可以少复制粘贴好多代码了。
虽说,现在建项目,已经能把一个大的模板完整的copy出来了,但是始终不是很灵活!
可能有小伙伴会问,明明已经很方便了呀,为什么还会说它不灵活呢?
且听我慢慢道来。
如果说这个模板是个大而全的模板,包含了中间件A,中间件B,中间件C等N个中间件!
而在建新项目的时候,已经明确了只用中间件A,那么其他的中间件对我们来说,可能就没有太大的存在意义!
很多时候,不会想让这些多余的文件出现在代码中,有没有办法来控制呢?
答案是肯定的!可以把不需要的文件排除掉就可以了。
文件过滤
模板项目中有一个RequestLogMiddleware,就用它来做例子。
我们只需要做下面几件事就可以了。
第一步,在template.json中添加过滤
加入一个名字为EnableRequestLog的symbol。同时指定源文件
{
"author": "Catcher Wong",
//others...
"symbols":{
//是否启用RequestLog这个Middleware
"EnableRequestLog": {
"type": "parameter", //它是参数
"dataType":"bool", //bool类型的参数
"defaultValue": "false" //默认是不启用
}
},
"sources": [
{
"modifiers": [
{
"condition": "(!EnableRequestLog)", //条件,由EnableRequestLog参数决定
"exclude": [ //排除下面的文件
"src/TplDemo/Middlewares/RequestLogMiddleware.cs",
"src/TplDemo/Middlewares/RequestLogServiceCollectionExtensions.cs"
]
}
]
}
]
}
第二步,在模板的代码中做一下处理
主要是Startup.cs,因为Middleware就是在这里启用的。
using System;
//other using...
using TplDemo.Core;
if (EnableRequestLog)
using TplDemo.Middlewares;
endif
/// <summary>
///
/// </summary>
public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        //other code....
if (EnableRequestLog)
        //request Log
        app.UseRequestLog();
endif
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}
这样的话,只要EnableRequestLog是true,那么就可以包含这两段代码了。
下面更新一下已经安装的模板。
这个时候再去看它的帮助信息,已经可以看到我们加的参数了。
下面先建一个默认的(不启用RequestLog)
dotnet new tpl -n NoLog
这个命令等价于
dotnet new tpl -n WithLog -E false
下面是建好之后的目录结构和Startup.cs
可以看到RequestLog相关的东西都已经不见了。
再建一个启用RequestLog的,看看是不是真的起作用了。
dotnet new tpl -n WithLog -E true
可以看到,效果已经出来了。
下面在介绍一个比较有用的特性。动态切换,这个其实和上面介绍的内容相似。
动态切换
直接举个例子来说明吧。
假设我们的模板支持MSSQL, MySQL, PgSQL和SQLite四种数据库操作
在新建一个项目的时候,只需要其中一种,好比说要建一个PgSQL的,肯定就不想看到其他三种。
这里不想看到,有两个地方,一个是nuget包的引用,一个是代码。
上一小节是对某个具体的功能进行了开关的操作,这里有了4个,我们要怎么处理呢?
我们可以用类型是choice的参数来完成这个操作。
修改template.json,加入下面的内容
{
"author": "Catcher Wong",
//others
"symbols":{
"sqlType": {
"type": "parameter",
"datatype": "choice",
"choices": [
{
"choice": "MsSQL",
"description": "MS SQL Server"
},
{
"choice": "MySQL",
"description": "MySQL"
},
{
"choice": "PgSQL",
"description": "PostgreSQL"
},
{
"choice": "SQLite",
"description": "SQLite"
}
],
"defaultValue": "MsSQL",
"description": "The type of SQL to use"
},
"MsSQL": {
"type": "computed",
"value": "(sqlType == "MsSQL")"
},
"MySQL": {
"type": "computed",
"value": "(sqlType == "MySQL")"
},
"PgSQL": {
"type": "computed",
"value": "(sqlType == "PgSQL")"
},
"SQLite": {
"type": "computed",
"value": "(sqlType == "SQLite")"
}
}
}
看了上面的JSON内容之后,相信大家也知道个所以然了。有一个名为sqlType的参数,它有几中数据库选择,默认是MsSQL。
还另外定义了几个计算型的参数,它的取值是和sqlType的值息息相关的。
MsSQL,MySQL,PgSQL和SQLite这4个参数也是我们在代码里要用到的!!
修改csproj文件,让它可以根据sqlType来动态引用nuget包,我们加入下面的内容
同样的,代码也要做相应的处理
if (MsSQL)
using System.Data.SqlClient;
elif (MySQL)
using MySql.Data.MySqlClient;
elif (PgSQL)
using Npgsql;
else
using Microsoft.Data.Sqlite;
endif
protected DbConnection GetDbConnection()
{
if (MsSQL)
    return new SqlConnection(_connStr);
elif (MySQL)
    return new MySqlConnection(_connStr);
elif (PgSQL)
    return new NpgsqlConnection(_connStr);
else
    return new SqliteConnection(_connStr);
endif
}
修改好之后,同样要去重新安装这个模板,安装好之后,就可以看到sqlType这个参数了。
下面分别创建一个MsSQL和PgSQL的项目,用来对比和验证。
先后执行
dotnet new tpl -n MsSQLTest -s MsSQL
dotnet new tpl -n PgSQLTest -s PgSQL
然后打开对应的csproj
可以看到,PgSQL的,添加多了NPgsql这个包。而MsSQL的却没有。
同样的,DapperRepositoryBase也是一样的效果。在创建Connection对象的时候,都根据模板来生成了。
当然这个是在我们自己本地安装的模板,其他人是没有办法使用的。
如果想公开,可以发布到nuget上面去。如果是在公司内部共享,可以搭建一个内部的nuget服务,将模板上传到内部服务器里面去。
下面是一些可以开箱即用的模板:
https://dotnetnew.azurewebsites.net/
总结
有一个自己的项目模板(脚手架),还是很方便的。
一建生成自己需要的东西,减少了不必要的代码复制,可以将更多精力放在业务实现上。
在平时还是要有一些积累,当积累足够丰富之后,我们的脚手架可能就会变得十分强大。
参考文档
dotnet new下面默认的模板 https://github.com/aspnet/Templating
templating的源码 https://github.com/dotnet/templating
template.json的说明 https://github.com/dotnet/templating/wiki/Reference-for-template.json
dotnet cli的文档 https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet?tabs=netcore21
最后是文中的示例代码
Template
如果您认为这篇文章还不错或者有所收获,可以点击右下角的【推荐】按钮,因为你的支持是我继续写作,分享的最大动力!
作者:Catcher ( 黄文清 )
来源:http://catcher1994.cnblogs.com/
NET Core项目模板的更多相关文章
- 打造自己的.NET Core项目模板
		前言 每个人都有自己习惯的项目结构,有人的喜欢在项目里面建解决方案文件夹:有的人喜欢传统的三层命名:有的人喜欢单一,简单的项目一个csproj就搞定.. 反正就是萝卜青菜,各有所爱. 可能不同的公司对 ... 
- 使用 DotNet CLI 创建自定义的 WPF 项目模板
		描述 当我们安装完 DotNetCore 3.0 版本的 SDK 后,我们就可以创建基于 DotNetCore 的 WPF 项目模板,通过如下 CLI 可以方便快捷的创建并运行我们的项目: dotne ... 
- 在Centos7中创建.net core 项目,并用Apache做代理服务器部署.net core项目
		这一篇实例记录一次用Centos7创建并部署.net core项目的过程,希望能帮到用到的小伙伴. Kestrel 是 ASP.NET Core 项目模板中包括的默认 Web 服务器,Kestrel可 ... 
- Net core学习系列(四)——Net Core项目执行流程
		"跨平台"后的ASP.Net Core是如何接收并处理请求的呢? 它的运行和处理机制和之前有什么不同?本章从"宏观"到"微观"地看一下它的结 ... 
- 从零开始实现ASP.NET Core MVC的插件式开发(二) - 如何创建项目模板
		标题:从零开始实现ASP.NET Core MVC的插件式开发(二) - 如何创建项目模板 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11155 ... 
- 使用 .NET CORE 创建 项目模板,模板项目,Template
		场景:日常工作中,你可能会碰到需要新建一个全新的解决方案的情况(如公司新起了一个新项目,需要有全新配套的后台程序),如果公司内部基础框架较多.解决方案需要DDD模式等,那么从新起项目到各种依赖引用到能 ... 
- .NET Core - 自定义项目模板
		前言: 前面介绍 自定义项目模板 中介绍了一种简单的方式--通过创建项目导出为项目模板方式实现.本次将采用dotenet cil(手脚架)来创建项目模板. 那么,我们首先看下当前dotnet 支持的项 ... 
- asp.net core web 解决方案多项目模板制作打包总结
		一.文件夹\项目结构 1.1.文件夹 net6.0:针对.net 6.0 项目模板 net6.0pack:针对net6.0打包 1.2.项目结构 Web\WebApi多项目.各层项目.单元测试项目 目 ... 
- 在传统.NET Framework 上运行ASP.NET Core项目
		新的项目我们想用ASP.NET Core来开发,但是苦于我们历史的遗产很多,比如<使用 JavaScriptService 在.NET Core 里实现DES加密算法>,我们要估计等到.N ... 
随机推荐
- nlp基本知识点(不断更新)
			1.精确率与召回率 召回率也称为查全率,指的是:你查询到的相关数目/(你查询到的相关的数目+你没有查询到的相关的数目). 精确率: A/A+B 召回率:A/A+C 再比如: 我 是 中国人 这里正确的 ... 
- java高级特性(2)--循序渐进地培养面向对象的思维方式
			在我踏入软件行业后,一直苦于没有前辈指点.我常年困惑于两个问题:一是怎样培养面向对象设计的思维能力?二是怎样进行架构设计,有无方法? 因为我做了那么多年项目,却很少看到有漂亮的面向对象思维写出来的代码 ... 
- 最简js深浅拷贝说明
			1.浅拷贝 浅拷贝是拷贝引用,拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响. 浅拷贝分两种情况: 1.直接拷贝源对象的引用 2. 源对象拷贝实例,但其属性对象(类型为Object, ... 
- spring mvc: 生成RSS源
			spring mvc: 生成RSS源 准备: 从相同的maven存储库页面下载 Rome 库及其依赖项rome-utils,jdom和slf4j.和所需的依赖关系 <!-- rss源依赖 --& ... 
- pahlcon:循环调度(Dispatch Loop)或跳转
			循环调度将会在分发器执行,直到没有action需要执行为止.在上面的例子中,只有一个action 被执行到.现在让我们来看下“forward”(转发)怎样才能在循环调度里提供一个更加复杂的操作流,从而 ... 
- Codeforces Round #378 (Div. 2)F - Drivers Dissatisfaction	GNU
			http://codeforces.com/contest/733/problem/F 题意:给你一些城市和一些路,每条路有不满意程度和每减少一点不满意程度的花费,给出最大花费,要求找出花费小于s的最 ... 
- macOS和常用命令
			macOS 常用命令 1. 显示“任何来源”选项 sudo spctl --master-disable 2. 阻止屏保和睡眠 caffeinate -t 3600 这是一个BSD命令.-t可选,按C ... 
- Regression 手动实现Gradient Descent
			import numpy as np import matplotlib.pyplot as plt x_data = [338.,333.,328.,207.,226.,25.,179.,60.,2 ... 
- JS返回一个数据的千分位格式
			/** * 价钱转换-从右往左每3位数字加一个逗号 * @param price 需要转换的价格 */ formatPrice(price){ var newPrice = price.split(' ... 
- springboot跳转jsp页面
			springboot支持jsp页面跳转 官方不推荐jsp的支持(jar包不支持jsp,jsp需要运行在servletContext中,war包需要运行在server服务器中如tomcat)官方推荐使用 ... 
