缘起
开工是利啦!哈喽各位小伙伴,周三好呀,新的一年又开始了,老张给大家做个榜样,新的一年也要好好学习哟,这两天闲的无事就整理整理了这个系列的 Github 代码,增加了一个英文的 README ,然后把 netcore2.0 合并到了项目里,并新建了一个2.0的分支,相信有些小伙伴应该也发现了,本来想试试 core 3.0版本,发现必须要安装 Visual Studio 2019 版本,可怜电脑已经安装了 vs15 和 vs17,所以就放弃了安装vs19,等明年,哦不对,是今年😂微软正式发布3.0的时候,再整理一个分支吧(以后肯定会有新的内容一直更新的)。
在整理代码的时候,我想到,上周在《38 ║自动初始化数据库(不定期更新)》中,我把项目的自动创建数据库并添加种子数据的功能给加上了,给大家提供了一个思路,以后大家创建项目可以这么玩儿,个人感觉还是很方便的,于是我就想到了一个问题,应该是只要开发一定时间的小伙伴,都会遇到的问题:
情景:自己经过多年开发的沉淀后,开发出一个属于自己的一套Demo项目,亦或是借鉴别人的项目后,优化了一个。比如我的第一个项目,采用 IService+ IRepository 分层的;或者比如我的第二个项目,采用DDD领域驱动+CQRS模式的。然后我们在别的地方使用的时候(可能是下一个公司),如果还想用自己的模板,也可能是供新入职的同事使用,经常会是以下几个办法,大家看看你属于哪一种:
0、对比着之前的项目结构,在VistulStudio中手动创建一个空的解决方案,从零开始,一点一点搭建。// 麻烦之大,可想而知
1、通过dotnet cli 命令来创建空项目,然后手动。// 会简化一丢丢,但仍需要一层一层的创建类库;
2、把Demo工程代码里拷贝到U盘,或者上传到云盘,然后下载下来,改吧改吧。// 寻找过程很麻烦,依赖代码承载工具;
3、把Demo工程代码 Pull 到 Github 上,在别的地方直接 Clone ,然后改吧改吧。 // 开源出源码,私密性不强;
大家可以看到,上边的这几个办法,都会有这样或那样的问题,快的不方便,方便的太局限。这个时候你会说,这怎么可能天天创建工程,有时候一个项目搭建好了能用一年,当然,这种也是有的,但是总会有新项目的,而且上边的这些都有一个通病,不知道大家是否发现:就是不能快速修改工程名称!举个栗子,我的这个 Github 上的项目,大家下载下来,怎么快速把 Blog.Core 改成 HelloBlog 呢?
这个时候我想到了一个东西,大家平时的时候应该用到过,就是使用 dotnet CLI 创建一个 net core api 项目是怎么做的呢:
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">// 通过命令行创建 core api项目
dotnet new webapi</pre>
这么创建好了以后,我们就可以自己一点一点的搭建项目了,这个时候我就想,那既然有 webapi 这个模板,我们自定义一个属于自己的一个或多个模板不就行了?!到时候只需要这么简单的输入一行命令,就能生成一套项目,各层明确,引用清晰,能在任何有网的电脑上运行,并且直接就能跑,想想都会感觉很刺激,不是么?!比如这样:
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">// 通过自定义命令行创建自己的项目
dotnet new 我是模板名称 -n HelloBlog</pre>
好啦,开始今天的讲解 —— 自定义dotnet 模板,很简单,只要你按照我的一步一步往下走,一定会看得懂。如果你看完本文,对你有帮助,请点个赞👍或评论📑哟。
最终的效果是这样的:
一、准备自己的Demo项目模板
1、开发一个空的并编译通过的项目
既然咱们要创建一个自定义的 dotnet 项目模板,那就必须自己先有自己的一套Code,有了这套 code,我们才能导入到 dotnet cli 模板库中使用。
今天呢,我就使用咱们的这个Blog.Core 项目了(https://github.com/anjoy8/Blog.Core),如果你想用自己的模板,前提是:
1、必须Code已经成型了,意思就是说,分层清楚,引用明确,只不过没有复杂的内容。
2、必须编译成功,不能有任何错误,否则后边会各种麻烦。
3、尽量能跑起来,就是能显示出界面,当然也不是必要条件,比如如果你新建了控制台程序,是没有web页面的。
4、一般不要把生成的dll文件包含其中,如果你下载我的Github代码,会发现只有400k,因为我把可执行文件都过滤了。
今天呢,我就手把手把咱们的这套代码给原封不动的分发导入到 dotnet 模板库中,比如这样(这是我本机测试的,正式模板会在下文详细说明):
除了咱们的这个项目,以后我还会建立一个基于DDD领域驱动设计的 dotnet 模板,这里先留个坑,到时候把命令行放到这里:(dotnet new -i xxxxxxx)
当然你也可以创建一个,如果你的项目比较好,看完这篇文章后,可以在下边留言哟,让大家都使用使用。
因为使用咱们这个项目,所以这一步很简单,注意不要把项目编译后的dll文件包含里边,一方面打包的时候占资源,另一方面可能会出错,
那项目源代码准备好了,接下来怎么做呢,别着急,请往下看。
二、将 Demo 模板导入到dotnet模块库中
现在我们就需要把上边准备的项目导入 dotnet 模板了:
1、创建固定格式的源文件和文件夹
在你的电脑任何地方,新建一个模板文件夹temple,用于以后打包多个模板使用,比如我是这样的(尽量按照这个格式来:content文件夹包含code模板):
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">├── temple // 用来存放所有的模板
│ ├── BlogCoreTemple // BlogCore模板全部内容
│ │ ├── content // 存放Code 项目代码,可直接运行
│ │ │ ├── Blog.Core
│ │ │ ├── .
│ │ │ ├── .
│ │ │ ├── .
│ │ │ ├── Blog.Core.Services
│ │ │ └── Blog.Core.sln
│ │ │
│ │ ├── license // 存放版本许可信息,如果不添加,后边会警告,文章后边会提到
│ │ │ └── license.txt
│ │ │
│ │ └── 其他待定 // 这里文章后边会打包的时候用到
│ │
│ └── DDDTemple // DDD模板信息</pre>
2、用于定义模板的配置文件 (template.json)
既然我们要自定义模板,那我们就必须配置,比如作者信息,比如模板名称,要不然dotnet咋知道哪一个模板是你自定义的呢。接下来咱们定义配置文件:
- 向源代码项目的根目录添加 .template.config 文件夹(注意是文件夹),到时候与它同级的文件都会被打包。
- 在 .template.config 文件夹中,创建 template.json 文件来配置模板。
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">{ "$schema": "http://json.schemastore.org/template",//template.json 文件的 JSON 架构,可以不要该键值对
"author": "lao zhang", //必填!模板创建者
"classifications": [ "Web/WebAPI" ], //必填,这个对应模板的Tags,其他的比如 [ "Common", "Console" ],
"name": "Blog.Core Dotnet", //必填,这个是模板名,比如ASP.NET Core Web API
"identity": "Blog.Core.Template", //可选,模板的唯一名称
"shortName": "blogcoretpl", //必填,这个对应模板的短名称,比如webapi
"tags": { "language": "C#" , "type":"project" }, "sourceName": "Blog.Core", // 可选,要替换的名字,这个就是模板的项目名,以后新建的时候,会把这个名字替换成其他,比如HelloBlog(警告!这里不要写一些专用词汇,比如app呀,net呀,core之类的)
"preferNameDirectory": true // 可选,添加目录
}</pre>
提示:这个模板被执行分发,添加到 dotnet 模板后,尽量保存好,不要删掉,因为如果删掉后,如果以后想卸载这个本地的模板,就不能了。
若要从本地文件系统卸载模板,需要完全限定路径。 例如,C:\Users<USER>\Documents\Templates\GarciaSoftware.ConsoleTemplate.CSharp 有效。
详细信息可以查看官网:https://docs.microsoft.com/zh-cn/dotnet/core/tools/custom-templates
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">├── temple // 用来存放所有的模板
│ ├── BlogCoreTemple // BlogCore模板全部内容
│ │ ├── content // 存放Code 项目代码,可直接运行
│ │ │ ├── .template.config // 模板配置文件夹
│ │ │ │ └── template.json // 配置文件
│ │ │ ├── Blog.Core
│ │ │ ├── .
│ │ │ ├── .
│ │ │ ├── .
│ │ │ ├── Blog.Core.Services
│ │ │ └── Blog.Core.sln
│ │ │
│ │ ├── license // 存放版本许可信息,如果不添加,后边会警告,文章后边会提到
│ │ │ └── license.txt
│ │ │
│ │ └── 其他待定 // 这里文章后边会打包的时候用到
│ │
│ └── DDDTemple // DDD模板信息</pre>
3、使用文件系统分发
经过上面两步的处理,咱们已经把模板源代码准备好了,并且也按照固定的规则,把配置文件配置好了,接下来就是来分发了,白话就是说:把代码导入到 dotnet 模板里。
这个是很简单的,代码DOS命令窗口,输入命令(注意文件夹的路径):
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">// 使用文件分发模板, // 注意文件路径:content文件夹的上一级,可以对比上边的截图中的文件夹结构
dotnet new -i D:\myTpl\temple\BlogCoreTemple</pre>
这个时候你会发现,系统中已经有了我们的模板!(我为了区别下文的第二种方法,故意在模板后加了个22)
与此对应的,就是卸载了,注意刚刚的那个文件地址不要删了(就是把新建的字母 i 变成了 u):
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">dotnet new -u D:\myTpl\temple\BlogCoreTemple</pre>
4、使用dotnet新模板创建一个项目
随便找一个其他文件夹,然后执行我们的操作:
成功了有没有!是不是很方便!以后我们把我们的项目模板导入到本地的 dotnet 中,就可以很快的搭建一个一模一样的项目(这个时候如果你运行 dotnet run会报错,因为我们解耦了,会找不到service.dll文件,我们手动F6编译即可),而且项目名称也可以自定义是不是很给力!至少我是感觉挺方便的。
但是,我开心了一分钟后,发现了这个方法的一个弊端,聪明的你应该也发现了,因为我们使用的是文件发布,所以我们只能在本机使用(不信的话,你可以在你电脑上执行下这个命令 dotnet new blogcoretpl22,肯定报错),那如果在家里,或者在新的公司,亦或让新来的同事使用这个模板,该如何使用呢,总不能又要重蹈覆辙,开始拷贝代码吧,哦NO!肯定不想这样,作为强迫症的我,肯定感觉不是很爽,那怎么办呢,别慌,下边的方法可以完美的解决这个问题!
三、发布 Demo 项目到 Nuget
1、添加 nuspec 范本文件
在 content 文件夹旁边,添加 nuspec 文件。 nuspec 文件是 XML 清单文件,用于描述包内容,并促进创建 NuGet 包。
重要:感谢小伙伴@ jamee1696 提醒!下边范本文件中的汉字只是我的解释说明,如果你自己做,请千万要去掉,不能带中文字符!
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;"><?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>Blog.Core.Webapi.Template</id>// nuget包标识,在 nuget.org 或包驻留的任意库中必须是唯一的
<version>1.0.0</version>// 遵循 major.minor.patch 模式的包版本。
<description> Creates a blog core webapi app.// 用于 UI 显示的包的详细说明。
</description>
<authors>Lao zhang</authors>// 包创建者的逗号分隔列表,与 nuget.org 上的配置文件名称一致
<packageTypes>
<packageType name="Template" />// 包类型
</packageTypes>
<license type="file">license\license.txt</license>// 上文提到的许可证信息
</metadata>
</package></pre>
2、下载Nuget.exe
上边配置好了,那怎么如何打包呢,现在咱们就需要 nuget.exe 工具了:https://www.nuget.org/downloads ,下载最新的exe文件即可,注意这个不是安装文件,这个需要配合着项目使用,如果你双击是无效的,把下载好的 nuget.exe 拷贝到 nuspec 范本文件同级的目录中:
3、生成Nupkg包
文件也配置好了,nuget执行文件也下载好了,接下来咱们就是正式开始打包了:
打开 DOS 命令窗口,进入到当前文件夹,然后直接运行打包命令:(注意打包的文件,是咱们创建的 nuspec 范本文件)
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">// 执行打包操作,文件地址就是 nuspec 范本地址
nuget pack D:\myTpl\temple\BlogCoreTemple\Blog.Core.Webapi.Template.nuspec</pre>
发现我们以及打包成功:
注意:这里有小伙伴提示错误nuget 命令行无效 ,你需要在nuget.exe 目录里操作,并且是 CMD 命令窗口,不是 powershell
当然你也可以这样:
将文件夹添加到 nuget.exe
中放置 PATH 环境变量的位置,这样就可以从任意位置使用 CLI 工具。
4、发布到nuget.org(注意质量)
提醒下,大家要注意模板的质量,尽量不要过多的上传打包哟。
接下来就是最后一步了,将我们打包成功的 nupkg 包,发布到 nuget.org ,这里有多种方法,我只演示web门户操作:
首先你需要在 nuget.org 官网注册账号,这里不细说,然后点击到上传页面:https://www.nuget.org/packages/manage/upload
-
选择 nuget.org 顶部菜单中的“上传”,并浏览到包位置。
nuget.org 告知包名称是否可用。 如果无法使用,则更改项目中的包标识符、重新生成,并重试上传。
如果包名称可用,nuget.org 将打开“验证”部分,可以在其中查看包清单中的元数据。 若要更改任何元数据,请编辑项目(项目文件或
.nuspec
文件)、重新生成、重新创建包,然后再次上传。在“导入文档”下,可以粘贴 Markdown、将 URL 指向文档,或上传文档文件。
当所有信息准备就绪后,选择“提交”按钮
上传成功后,nuget 会后台进行扫描病毒,然后进行发布,中间大概等待10分钟后,你会收到一个官方的邮件,提示你已经发布成功:
地址:https://www.nuget.org/packages/Blog.Core.Webapi.Template/
四、Nuget包导入到dotnet模板,并创建新工程
1、使用nuget.org 的包ID进行分发
在上边发布成功了以后,我们直接就可以通过 nuget 唯一包id,来进行导入dotnet 模板操作:
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">// 通过nuget.org ID 导入分发,这个名称,就是我们之前在 nuspec 范本文件中,配置的nuget包 ID
dotnet new -i Blog.Core.Webapi.Template</pre>
然后就可以看到已经导入成功了,至于使用,就和之前的通过文件系统导入的是一样的:
是不是很不错!完全解放双手,也不依赖工具,就可以直接创建一套相同的项目,并可以自定义项目名:
不信的话,你可以在你电脑里执行下刚刚的那个模板导入命令(dotnet new -i Blog.Core.Webapi.Template),可以成功的导入到你的电脑里(注意一定要是管理员权限打开命令行窗口,如果报错,可能是401权限问题,请在下方留言)。如果你用不了这个命令,证明你的电脑是没有最高权限的,那就请用下边的这个方法吧。
2、直接使用nupkg包来导入
如果你不能直接用 nuget.org 的标识ID来分发模板,那就直接用 nupkg 包导入吧,下载本文中的包:https://www.nuget.org/api/v2/package/Blog.Core.Webapi.Template/1.0.0,或者用上边本地的打包好的,是一样的
然后执行命令:
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">// 将nupkg 包分发
dotnet new -i E:\my-file\temple\Blog.Core.Webapi.Template.1.0.0.nupkg</pre>
3、卸载模板
当然如果你不想要,也可以,很简单,直接执行这个命令就行
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">// 从 nuget.org 中存储的 NuGet 包卸载模板
dotnet new -u Blog.Core.Webapi.Template</pre>
五、结语
今天咱们主要讲解了如何把自己的源代码Demo项目,分发到 dotnet 模板中;然后又讲解了如何把自己的源代码项目进行 nuget 打包,并发布到 nuget.org 库中;
最后将发布到 nuget 包分发到 dotne 模板中,方便的在任何地方使用。
已经在GitHub 上添加了,大家可以下载看看:
然后在Nuget包管理器中,可以找到,只不过这是一个整个工程,大家不用添加到项目里,以后你如果创建一个Tool,可以添加到这里,还记得咱们的ORM么(https://github.com/anjoy8/AZLinli.ORM),我打算把这个提交上去,自己使用。
最终的文件结构是这样的:
<pre style="color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 12px; margin: 5px 8px; padding: 5px;">├── temple // 用来存放所有的模板
│ ├── BlogCoreTemple // BlogCore模板全部内容
│ │ ├── content // 存放Code 项目代码,可直接运行
│ │ │ ├── .template.config // 模板配置文件夹
│ │ │ │ └── template.json // 配置文件
│ │ │ ├── Blog.Core
│ │ │ ├── .
│ │ │ ├── .
│ │ │ ├── .
│ │ │ ├── Blog.Core.Services
│ │ │ └── Blog.Core.sln
│ │ │
│ │ ├── license // 存放版本许可信息,如果不添加,后边会警告,文章后边会提到
│ │ │ └── license.txt
│ │ │
│ │ ├── Blog.Core.Webapi.Template.nuspec // nuget 打包的范本配置文件
│ │ └── nuget.exe // nuget.exe 可执行文件
│ │
│ └── DDDTemple // DDD模板信息</pre>