更新:
1、如果想使用我的 Blog.Core 項目,並且又想快速重命名成自己的項目,請看這個Wiki:https://github.com/anjoy8/Blog.Core/wiki/Temple-Nuget
緣起
開工是利啦!哈嘍各位小伙伴,周三好呀,新的一年又開始了,老張給大家做個榜樣,新的一年也要好好學習喲,這兩天閑的無事就整理整理了這個系列的 Github 代碼,增加了一個英文的 README ,然后把 netcore2.0 合並到了項目里,並新建了一個2.0的分支,相信有些小伙伴應該也發現了,本來想試試 core 3.0版本,發現必須要安裝 Visual Studio 2019 版本,可憐電腦已經安裝了 vs15 和 vs17,所以就放棄了安裝vs19,等明年,哦不對,是今年😂微軟正式發布3.0的時候,再整理一個分支吧(以后肯定會有新的內容一直更新的)。
(目前是2.2版本,因作者開源的項目較多,維護成本過高,所以本項目其他分支不再提供支持)
在整理代碼的時候,我想到,上周在《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 項目是怎么做的呢:
// 通過命令行創建 core api項目 dotnet new webapi
這么創建好了以后,我們就可以自己一點一點的搭建項目了,這個時候我就想,那既然有 webapi 這個模板,我們自定義一個屬於自己的一個或多個模板不就行了?!到時候只需要這么簡單的輸入一行命令,就能生成一套項目,各層明確,引用清晰,能在任何有網的電腦上運行,並且直接就能跑,想想都會感覺很刺激,不是么?!比如這樣:
// 通過自定義命令行創建自己的項目 dotnet new 我是模板名稱 -n HelloBlog
好啦,開始今天的講解 —— 自定義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模板):
├── temple // 用來存放所有的模板 │ ├── BlogCoreTemple // BlogCore模板全部內容 │ │ ├── content // 存放Code 項目代碼,可直接運行 │ │ │ ├── Blog.Core │ │ │ ├── . │ │ │ ├── . │ │ │ ├── . │ │ │ ├── Blog.Core.Services │ │ │ └── Blog.Core.sln │ │ │ │ │ ├── license // 存放版本許可信息,如果不添加,后邊會警告,文章后邊會提到 │ │ │ └── license.txt │ │ │ │ │ └── 其他待定 // 這里文章后邊會打包的時候用到 │ │ │ └── DDDTemple // DDD模板信息
2、用於定義模板的配置文件 (template.json)
既然我們要自定義模板,那我們就必須配置,比如作者信息,比如模板名稱,要不然dotnet咋知道哪一個模板是你自定義的呢。接下來咱們定義配置文件:
- 向源代碼項目的根目錄添加 .template.config 文件夾(注意是文件夾),到時候與它同級的文件都會被打包。
- 在 .template.config 文件夾中,創建 template.json 文件來配置模板。
{ "$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 // 可選,添加目錄 }
提示:這個模板被執行分發,添加到 dotnet 模板后,盡量保存好,不要刪掉,因為如果刪掉后,如果以后想卸載這個本地的模板,就不能了。
若要從本地文件系統卸載模板,需要完全限定路徑。 例如,C:\Users\<USER>\Documents\Templates\GarciaSoftware.ConsoleTemplate.CSharp 有效。
詳細信息可以查看官網:https://docs.microsoft.com/zh-cn/dotnet/core/tools/custom-templates
├── temple // 用來存放所有的模板 │ ├── BlogCoreTemple // BlogCore模板全部內容 │ │ ├── content // 存放Code 項目代碼,可直接運行 │ │ │ ├── .template.config // 模板配置文件夾 │ │ │ │ └── template.json // 配置文件 │ │ │ ├── Blog.Core │ │ │ ├── . │ │ │ ├── . │ │ │ ├── . │ │ │ ├── Blog.Core.Services │ │ │ └── Blog.Core.sln │ │ │ │ │ ├── license // 存放版本許可信息,如果不添加,后邊會警告,文章后邊會提到 │ │ │ └── license.txt │ │ │ │ │ └── 其他待定 // 這里文章后邊會打包的時候用到 │ │ │ └── DDDTemple // DDD模板信息
3、使用文件系統分發
經過上面兩步的處理,咱們已經把模板源代碼准備好了,並且也按照固定的規則,把配置文件配置好了,接下來就是來分發了,白話就是說:把代碼導入到 dotnet 模板里。
這個是很簡單的,代碼DOS命令窗口,輸入命令(注意文件夾的路徑):
// 使用文件分發模板, // 注意文件路徑:content文件夾的上一級,可以對比上邊的截圖中的文件夾結構 dotnet new -i D:\myTpl\temple\BlogCoreTemple
這個時候你會發現,系統中已經有了我們的模板!(我為了區別下文的第二種方法,故意在模板后加了個22)
與此對應的,就是卸載了,注意剛剛的那個文件地址不要刪了(就是把新建的字母 i 變成了 u):
dotnet new -u D:\myTpl\temple\BlogCoreTemple
4、使用dotnet新模板創建一個項目
隨便找一個其他文件夾,然后執行我們的操作:
成功了有沒有!是不是很方便!以后我們把我們的項目模板導入到本地的 dotnet 中,就可以很快的搭建一個一模一樣的項目(這個時候如果你運行 dotnet run會報錯,因為我們解耦了,會找不到service.dll文件,我們手動F6編譯即可),而且項目名稱也可以自定義是不是很給力!至少我是感覺挺方便的。
但是,我開心了一分鍾后,發現了這個方法的一個弊端,聰明的你應該也發現了,因為我們使用的是文件發布,所以我們只能在本機使用(不信的話,你可以在你電腦上執行下這個命令 dotnet new blogcoretpl22,肯定報錯),那如果在家里,或者在新的公司,亦或讓新來的同事使用這個模板,該如何使用呢,總不能又要重蹈覆轍,開始拷貝代碼吧,哦NO!肯定不想這樣,作為強迫症的我,肯定感覺不是很爽,那怎么辦呢,別慌,下邊的方法可以完美的解決這個問題!
三、發布 Demo 項目到 Nuget
1、添加 nuspec 范本文件
在 content 文件夾旁邊,添加 nuspec 文件。 nuspec 文件是 XML 清單文件,用於描述包內容,並促進創建 NuGet 包。
重要:感謝小伙伴@ jamee1696 提醒!下邊范本文件中的漢字只是我的解釋說明,如果你自己做,請千萬要去掉,不能帶中文字符!
<?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>
2、下載Nuget.exe
上邊配置好了,那怎么如何打包呢,現在咱們就需要 nuget.exe 工具了:https://www.nuget.org/downloads ,下載最新的exe文件即可,注意這個不是安裝文件,這個需要配合着項目使用,如果你雙擊是無效的,把下載好的 nuget.exe 拷貝到 nuspec 范本文件同級的目錄中:
3、生成Nupkg包
文件也配置好了,nuget執行文件也下載好了,接下來咱們就是正式開始打包了:
打開 DOS 命令窗口,進入到當前文件夾,然后直接運行打包命令:(注意打包的文件,是咱們創建的 nuspec 范本文件)
// 執行打包操作,文件地址就是 nuspec 范本地址 nuget pack D:\myTpl\temple\BlogCoreTemple\Blog.Core.Webapi.Template.nuspec
發現我們以及打包成功:
注意:這里有小伙伴提示錯誤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/
具體的參考官網:https://docs.microsoft.com/zh-cn/nuget/create-packages/publish-a-package#package-validation-and-indexing
四、Nuget包導入到dotnet模板,並創建新工程
1、使用nuget.org 的包ID進行分發
在上邊發布成功了以后,我們直接就可以通過 nuget 唯一包id,來進行導入dotnet 模板操作:
// 通過nuget.org ID 導入分發,這個名稱,就是我們之前在 nuspec 范本文件中,配置的nuget包 ID dotnet new -i Blog.Core.Webapi.Template
感謝網友 @改啊變 提醒,這里可以選擇不同的版本,帶上 ::version 1.0.0。 不帶的話,默認是最新的:
dotnet new -i Blog.Core.Webapi.Template::version 1.0.0
然后就可以看到已經導入成功了,至於使用,就和之前的通過文件系統導入的是一樣的:
是不是很不錯!完全解放雙手,也不依賴工具,就可以直接創建一套相同的項目,並可以自定義項目名:
不信的話,你可以在你電腦里執行下剛剛的那個模板導入命令(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,或者用上邊本地的打包好的,是一樣的
然后執行命令:
// 將nupkg 包分發 dotnet new -i E:\my-file\temple\Blog.Core.Webapi.Template.1.0.0.nupkg
3、卸載模板
當然如果你不想要,也可以,很簡單,直接執行這個命令就行
// 從 nuget.org 中存儲的 NuGet 包卸載模板 dotnet new -u Blog.Core.Webapi.Template
五、結語
今天咱們主要講解了如何把自己的源代碼Demo項目,分發到 dotnet 模板中;然后又講解了如何把自己的源代碼項目進行 nuget 打包,並發布到 nuget.org 庫中;
最后將發布到 nuget 包分發到 dotne 模板中,方便的在任何地方使用。
已經在GitHub 上添加了,大家可以下載看看:
然后在Nuget包管理器中,可以找到,只不過這是一個整個工程,大家不用添加到項目里,以后你如果創建一個Tool,可以添加到這里,還記得咱們的ORM么(https://github.com/anjoy8/AZLinli.ORM),我打算把這個提交上去,自己使用。
( 上邊打包的項目,在 Nuget 包中可以搜到)
最終的文件結構是這樣的:
├── 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模板信息
六、Github & Gitee
https://github.com/anjoy8/Blog.Core
https://gitee.com/laozhangIsPhi/Blog.Core