打造自己的.NET Core项目模板

前言

每个人都有自己习惯的项目结构,有人的喜欢在项目里面建解决方案文件夹;有的人喜欢传统的三层命名;有的人喜欢单一,简单的项目一个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包,我们加入下面的内容

<ItemGroup Condition="'$(MySQL)' == 'True' ">
  <PackageReference Include="MySqlConnector" Version="0.47.1" />
</ItemGroup>

<ItemGroup Condition="'$(PgSQL)' == 'True' ">
  <PackageReference Include="Npgsql" Version="4.0.3" />
</ItemGroup>

<ItemGroup Condition="'$(SQLite)' == 'True' ">
  <PackageReference Include="Microsoft.Data.Sqlite" Version="2.1.0" />
</ItemGroup>

同样的,代码也要做相应的处理

#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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ASP.NET Core MVC/WebApi基础系列2

    >前言 好久没冒泡了,算起来估计有快半年没更新博客了,估计是我第一次停更如此之久,人总有懒惰的时候,时间越长越懒惰,但是呢,不学又不行,持续的惰性是不行dei,要不然会被时光所抛弃,技术所淘汰,好吧,进入今天的主题,本节内容,我们来讲讲.NET Core当中的模型绑定系统.模型绑定原理.自定义模型绑定.混合绑定.ApiController特性本质,可能有些园友已经看过,但是效果不太好哈,这篇是解释最为详细的一篇,建议已经学过我发布课程的童鞋也看下,本篇内容略长,请保持耐心,我只讲你们会用到的或者

  • win7-vs2012下安装.net frame work 的过程图文详解

    第一, vs和.net的对应关系大致如下 vs2010----.net framework 4.0 vs2012----.net framework 4.5 vs2015----.net framework 4.6.1 vs2017----.net framework 4.6.2 第二,在win7上安装vs2010之后会有.net4.5 frame work已经安装好了. vs2012 update5 也可以安装,但不是必须的. 第三,如果以后的开发不需要用到4.5.1 4.5.2 4.6 4.

  • .NET开发人员关于ML.NET的入门学习

    ML.NET一直在微软的研究部门的工作.这些创新已经用于他们自己的产品,如Windows Defender,Microsoft Office(Powerpoint设计理念,Excel图表推荐),Azure机器学习,PowerBI. ML.NET旨在提供终端工作流程,以便在机器学习(预处理,特征工程,建模,评估和操作)的各个步骤中将ML用于.NET应用程序. ML.NET 1.0提供以下关键组件:数据表示机器学习任务(分类,回归,异常检测等)数据特征工程 机器学习模型应该让分析师的生活更轻松,现在

  • ASP.NET Core MVC/WebApi基础系列1

    >前言 最近发表的EF Core貌似有点多,可别误以为我只专攻EF Core哦,私下有时间也是一直在看ASP.NET Core的内容,所以后续会穿插讲EF Core和ASP.NET Core,别认为你会用ASP.NET Core就自认为你很了解ASP.NET Core,虽说是基础系列但也是也有你不知道的ASP.NET Core. UseStaticFiles.UseDefaultFiles.UseDirectoryBrowser.UseFileServer 当我们创建默认.NET Core We

  • 浅谈从ASP.NET Core2.2到3.0你可能会遇到这些问题

    趁着假期的时间所以想重新学习下微软的官方文档来巩固下基础知识.我们都知道微软目前已经发布了.NET Core3.0的第三个预览版,同时我家里的电脑也安装了vs2019.So,就用vs2019+.NET Core3.0来跟着做一下Contoso University这个WEB应用,但是在基于3.0进行操作的时候遇到了一些问题,所以我就查看了微软的<从 ASP.NET Core 迁移 2.2 到 3.0 预览版 2>这篇文档,就着今天遇到的问题,所以我整理下,希望对大伙有所帮助,当然大伙也可以直接

  • .NET Core Dapper操作mysql数据库的实现方法

    前言 现在ORM盛行,市面上已经出现了N款不同的ORM套餐了.今天,我们不谈EF,也不聊神马黑马,就说说 Dapper.如何在.NET Core中使用Dapper操作Mysql数据库呢,让我们跟随镜头(手动下翻)一看究竟. 配置篇 俗话说得好,欲要善其事必先利其器.首先,我们要引入MySql.Data 的Nuget包.有人可能出现了黑人脸,怎么引入.也罢,看在你骨骼惊奇的份上,我就告诉你,两种方式: 第一种方式 Install-Package MySql.Data -Version 8.0.15

  • 打造自己的.NET Core项目模板

    前言 每个人都有自己习惯的项目结构,有人的喜欢在项目里面建解决方案文件夹:有的人喜欢传统的三层命名:有的人喜欢单一,简单的项目一个csproj就搞定.. 反正就是萝卜青菜,各有所爱. 可能不同的公司对这些会有特定的要求,也可能会随开发自己的想法去实践. 那么,问题就来了.如果有一个新项目,你会怎么去创建? 可能比较多的方式会是下面三种: 简单粗暴型,打开VS就是右键添加,然后引入一堆包,每个项目添加引用. 脚本型,基于dotnet cli,创建解决方案,创建项目,添加包,添加项目引用. 高大上型

  • 详解使用DotNet CLI创建自定义的WPF项目模板

    本文主要介绍了使用DotNet CLI创建自定义的WPF项目模板,分享给大家,具体如下: 描述 当我们安装完 DotNetCore 3.0 版本的 SDK 后,我们就可以创建基于 DotNetCore 的 WPF 项目模板,通过如下 CLI 可以方便快捷的创建并运行我们的项目: dotnet new wpf -n WpfApp cd WpfApp dotnet restore dotnet run 做过 WPF 开发的朋友都知道,这个项目模板肯定不符合我们的预期,我们希望我们的项目模板能够加入

  • .NET Core自定义项目模板的全过程

    前言: 前面介绍 自定义项目模板 中介绍了一种简单的方式--通过创建项目导出为项目模板方式实现.本次将采用dotenet cil(手脚架)来创建项目模板. 那么,我们首先看下当前dotnet 支持的项目模板: 可以看到当前dotnet中已经提供了很多模板项目,那么如何根据项目开发的积累内容通过dotnet cli创建一个自己的项目来提升开发效率呢? 1.实现自定义项目模板 自定义模板项目模板肯定就需要模板实现,本次就使用使用之前文章中项目结构作为模板项目来实现自定义项目模板 接下跟着步骤来创建模

  • 创建ASP.NET Core Web应用程序并介绍项目模板

    目录 创建ASP.NET Web 应用程序 运行ASP.NET Core Web 应用程序: ASP.NET Core应用程序模板 空 API Web应用程序模板 Web应用程序(模型视图-控制器)模板 Angular, React.js, React.js, and Redux: 创建ASP.NET Web 应用程序 打开安装后的VisualStudio 2019,点击"创建新项目", 如下所示. 单击"创建新项目"框后,它将打开"创建新项目"

  • ASP.NET如何自定义项目模板详解

    前言 在微服务架构盛行的时代,一言不合就新建一个服务,虽然搭建服务并没什么难度,但不可避免的是每个人搭建出来的架子会存在差异,这很合理,因为每个开发者的个人风格.工作经验都不一样,难免认为自己喜欢的才是最好的.另一方面,如果需要较频繁搭建服务,这些重复而没难度的操作就显得浪费时间,而且每次手动处理总可能存在一些细节上的失误,出现异常然后花时间解决更得不偿失. 面对以上一些问题,拥有一个符合自己团队的项目模板就显得比较重要了,这篇文章主要介绍在 ASP.NET 如果自定义项目模板. 内置的项目模板

  • .NET core项目AsyncLocal在链路追踪中的应用

    目录 前言 老传统做法 AspNetCore的TraceIdentifier AsyncLocal在链路追踪的应用 定义 示例 项目应用 AspNet4 AspNetCore 前言 在项目生产中日志的记录是必不可少的,在.net项目中,要说日志组件,log4net绝对可有一席之地,随着公司业务的发展,微服务则必定无可避免.在跨服务中通过日志进行分析性能或者排查故障点,如何快速定位日志尤为关键.链路追踪技术的出现正是解决这些痛点的. 分布式链路追踪需要收集单次请求所经过的所有服务,而且为了知道请求

  • ASP.NET Core项目配置教程(6)

    在这一章,我们将讨论 ASP.NET Core项目的相关的配置.在解决方案资源管理器中,您将看到 Startup.cs 文件.如果你有以前版本的 ASP.NET的工作经验,你可能希望看到一个 global.asax 文件,您可以在其中编写代码,它是一个编写程序启动时立即执行的代码的文件. 你可能也希望看到一个 web.config 文件,该文件包含您的应用程序执行所需的所有配置参数. 在 ASP.NET Core中,那些文件都没了,取而代之的是 Startup.cs文件. Startup.cs里

  • ASP.NET Core项目结构教程(4)

    在这一章,我们将讨论 ASP.NET Core项目在文件系统上的组成方式以及不同的文件和目录都是如何协同工作的. 让我们打开在前一章创建的FirstAppDemo项目. 在解决方案资源管理器窗口中,右击解决方案节点并选择"Open Folder in File Explorer". 您将看到在它的根目录下有两个文件︰ FirstAppDemo.sln和global.json. FirstAppDemo.sln文件是一个解决方案文件.Visual Studio多年来在默认情况下一直使用s

  • 在IIS上部署ASP.NET Core项目的图文方法

    概述 与ASP.NET时代不同,ASP.NET Core不再是由IIS工作进程(w3wp.exe)托管,而是使用自托管Web服务器(Kestrel)运行,IIS则是作为反向代理的角色转发请求到Kestrel不同端口的ASP.NET Core程序中,随后就将接收到的请求推送至中间件管道中去,处理完你的请求和相关业务逻辑之后再将HTTP响应数据重新回写到IIS中,最终转达到不同的客户端(浏览器,APP,客户端等).而配置文件和过程都会由些许调整,中间最重要的角色便是AspNetCoreModule,

  • Vue.js项目模板搭建图文教程

    前言 从今年(2017年)年初起,我们团队开始引入「Vue.js」开发移动端的产品.作为团队的领头人,我的首要任务就是设计 整体的架构 .一个良好的架构必定是具备丰富的开发经验后才能搭建出来的.虽然我有多年的前端开发经验,但就「Vue.js」来说,仍然是个新手.所幸「Vue.js」有一个配套工具「Vue-CLI」,它提供了一些比较成熟的项目模板,很大程度上降低了上手的难度.然而,很多具体的问题还是要自己思考和解决的. 项目划分 我们公司的H5产品大部分是嵌套在手机客户端里面的页面.每个项目的功能

随机推荐