1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
      <output id="hzk7v"></output>
    2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
    3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

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

       更新时间£º2019年04月15日 09:36:49   作者£ºCatcher8   我要评论

      这篇文章主要介绍了打造自己的.NET Core项目模板£¬文中通过示例代码介绍的非常详细£¬对大家的学习或者工作具有一定的参考学习价值£¬需要的朋友们下面随着小编来一起学习学习吧

      前言

      每个人都有自己习惯的项目结构£¬有人的喜?#23545;?#39033;目里面建解决方案文件夹£»有的人喜欢传统的三层命名£»有的人喜欢单一£¬简单的项目一个csproj就搞定¡£¡£

      反正就是萝?#38750;?#33756;£¬各有所爱¡£

      可能不同的公司对这些会有特定的要求£¬也可能会随开发自己的想法去实践¡£

      那么£¬问题就来了¡£如果有一个新项目£¬你会怎么去创建£¿

      可能比较多的方式会是下面三种£º

      • 简单粗暴型£¬打开VS就是右键添加£¬然后引入一堆包£¬每个项目添?#21491;?#29992;¡£
      • 脚本型£¬基于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£¬这是个可选的字段£¬它的值会替换指定的项目名£¬正常?#21069;?#39033;目名赋值在这里¡£如果不指定£¬创建的项目就和样例项目保持一致¡£

      在写完template.json之后£¬还需要安装一下这个模板到我们的cli中¡£

      使用 dotnet new -i进行模板的安装¡£

      下面是安装示例¡£

      dotnet new -i ./content/TplDemo

      这里要注意的是£¬与.template.config文件夹同级的目录£¬都会被打包进模板中¡£

      在执行安装命令之后£¬就可以看到我们的模板已经安装好了¡£

      这个时候已经迫不?#25353;?#30340;想来试试这个模板了¡£

      先来看看这个模板的帮助信息¡£

      dotnet new tpl -h

      因为我们目前还没有设置参数£¬所以这里显示的是还没有参数¡£

      下面来创建一个项目试试¡£

      从创建一个项目£¬到运行起来£¬很简单£¬效果也是我们预期的¡£

      下面来看看£¬新建的这个HelloTpl这个项目的目录结构和我们的模板是否一样¡£

      可以看到£¬除了名字£¬其他的内容都是一样的¡£

      是不是感觉又可以少复制?#31243;?#22909;多代码了¡£

      虽说£¬现在建项目£¬已经能把一个大的模板完整的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相关的东西?#23478;?#32463;不见了¡£

      再建一个启用RequestLog的£¬看?#35789;?#19981;是真的起作用了¡£

      dotnet new tpl -n WithLog -E true

      可以看到£¬效果已经出来了¡£

      下面在介绍一个比较有用的特性¡£动态切换£¬这个其实和上面介绍的内容相似¡£

      动态切换

      直接举个例子来说明吧¡£

      假设我们的模板支持MSSQL, MySQL, PgSQL和SQLite四种数据库操作

      在新建一个项目的时候£¬只需要其中一种£¬好?#20154;?#35201;建一个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内容之后£¬相信大家也知?#26639;?#25152;以然了¡£有一个名为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这个参数了¡£

      下面?#30452;?#21019;建一个MsSQL和PgSQL的项目£¬用来对比和验证¡£

      先后执行

      dotnet new tpl -n MsSQLTest -s MsSQL 
      dotnet new tpl -n PgSQLTest -s PgSQL

      然后打开对应的csproj

      可以看到£¬PgSQL的£¬添加多了NPgsql这个包¡£而MsSQL的却没有¡£

      同样的£¬DapperRepositoryBase也是一样的效果¡£在创建Connection对象的时候£¬都根据模板来生成了¡£

      ?#27604;?#36825;个是在我们自己本地安装的模板£¬其他人是没有办法使用的¡£

      如果想公开£¬可以发布到nuget上面去¡£如果是在公司内部共享£¬可?#28304;?#24314;一个内部的nuget服务£¬将模板上传到内部服务器里面去¡£

      下面是一些可以开箱即用的模板£ºhttps://dotnetnew.azurewebsites.net/

      总结

      有一个自己的项目模板(脚手架)£¬还是很方便的¡£

      一建生成自己需要的东西£¬减少了不必要的代码复制£¬可以将更多精力放在业务实现上¡£

      在平时还是要有一些积累£¬?#34987;?#32047;足够丰富之后£¬我们的脚手架可能就会变得十分强大¡£

      参考文档

      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

      以上就是本文的全部内容£¬希望对大家的学习有所帮助£¬也希望大家多多支持脚本之家¡£

      相关文章

      最新评论

      3dÊÔ»úºÅÖвÊÍø

        1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
          <output id="hzk7v"></output>
        2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
        3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

            1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
              <output id="hzk7v"></output>
            2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
            3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>