电竞比分网-中国电竞赛事及体育赛事平台

分享

使用 .NET Core模板引擎創(chuàng)建自定義的模板和項目

 風聲之家 2021-04-03

WEB前端開發(fā)社區(qū) 昨天

本文是我們 .NET教育系列的一部分,該教育系列探討了 .NET 技術的好處,以及它是如何不僅可以幫助傳統(tǒng)的 .NET 開發(fā)人員,還可以幫助所有想要為市場提供可靠、高效且經(jīng)濟的解決方案的技術人員的。
隨著 .NET Core 3.0 的發(fā)布,微軟擁有了通用、模塊化、跨平臺和開源平臺的下一個主要版本,該版本最初是在 2016 年發(fā)布的。.NET Core 最初是為了支持下一代 ASP.NET 解決方案而創(chuàng)建的,但現(xiàn)在它驅動了許多其他場景,包括物聯(lián)網(wǎng)、云和下一代移動解決方案,并且是這些場景的基礎。3.0 版本增加了許多常用的特性,比如對 WinForms、WPF 和 Entity Framework 6 的支持。
由于 .NET Core 對命令行的重視,導致它的工具發(fā)生了巨大的變化。這非常適用于 .NET Core 跨平臺、工具無關的鏡像。dotnet CLI 是實現(xiàn)這些優(yōu)勢功能的入口點,它包含了許多用于創(chuàng)建、編輯、構建和打包 .NET Core 項目的不同命令。在本文中,我們僅關注 dotnet CLI 的一個方面:dotnet new 命令。
該命令主要用于創(chuàng)建項目,學習過程中,我們經(jīng)常會創(chuàng)建一個簡單的樣板項目,然后就把它忘掉了。本文中,我們將學習如何充分利用這個命令,通過傳遞參數(shù)來修改已生成的項目,并將學習如何使用該命令來創(chuàng)建文件和項目。我們還將看到這個工具是一個成熟的模板引擎,它不僅可以用來安裝自定義模板,還可以用來制作個人模板。

dotnet new 實踐

要怎樣使用 dotnet new 呢?讓我們從頭開始,直到找出最有趣的部分。要創(chuàng)建一個簡單的控制臺應用程序,那么先啟動命令行,將目錄切換為一個新的空文件夾(這是一個重要步驟,后面將會對此進行說明),然后調(diào)用 dotnet new console:
> dotnet new console
The template "Console Application" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on /Users/matt/demo/MyNewApp/MyNewApp.csproj...
Restoring packages for /Users/matt/demo/MyNewApp/MyNewApp.csproj...
Generating MSBuild file /Users/matt/demo/MyNewApp/obj/MyNewApp.csproj.nuget.g.props.
Generating MSBuild file /Users/matt/demo/MyNewApp/obj/MyNewApp.csproj.nuget.g.targets.
Restore completed in 234.92 ms for /Users/matt/demo/MyNewApp/MyNewApp.csproj.

Restore succeeded.
正如前面提到的,首先確保我們在一個新的空文件夾中。默認情況下,dotnet new 將會在當前文件夾中創(chuàng)建文件,并且不會刪除已經(jīng)存在的文件。我們可以使用 --output  選項創(chuàng)建一個新文件夾。例如,可以通過鍵入如下命令在名為 ConsoleApp42 的新文件夾中創(chuàng)建項目:
> dotnet new console --output ConsoleApp42
The template "Console Application" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on ConsoleApp42/ConsoleApp42.csproj...
Restoring packages for /Users/matt/demo/ConsoleApp42/ConsoleApp42.csproj...
Generating MSBuild file /Users/matt/demo/ConsoleApp42/obj/ConsoleApp42.csproj.nuget.g.props.
Generating MSBuild file /Users/matt/demo/ConsoleApp42/obj/ConsoleApp42.csproj.nuget.g.targets.
Restore completed in 309.99 ms for /Users/matt/demo/ConsoleApp42/ConsoleApp42.csproj.
Restore succeeded.

看看創(chuàng)建了什么

此時,dotnet new 已經(jīng)創(chuàng)建了一個新的控制臺項目,并且還原了 NuGet 包(它已經(jīng)準備好運行了)。但是,讓我們先看下我們到底創(chuàng)建了什么:
> ls ConsoleApp42/ConsoleApp42.csproj  Program.cs           obj/
可以看到,現(xiàn)在有了一個基于輸出文件夾名稱的項目文件。如果我們需要,也可以使用 --name 參數(shù)來指定一個不同的名稱:
dotnet new console --output ConsoleApp42 --name MyNewApp
它將在名為 ConsoleApp42 的文件夾中創(chuàng)建項目文件,并使用 MyNewApp 作為正在創(chuàng)建的控制臺應用程序的名稱,我們將得到一個 MyNewApp.csproj。如果我們查看 Program.cs,還將看到該 name 參數(shù)也被用來更新命名空間了:
using System;

namespace ConsoleApp42
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}

為另一個項目做準備

但是,如果我們查看一下我們剛才創(chuàng)建的項目的文件夾目錄結構,可能會發(fā)現(xiàn)它丟失了一些內(nèi)容,它沒有解決方案文件。我們只有一個項目,雖然它可以在 dotnet run 時正常運行,但當我們添加另一個項目時,它將會引起問題。我們可以輕松創(chuàng)建一個項目:

該命令將創(chuàng)建一個新的空解決方案文件。然后,向其中添加項目是另外的步驟。
如果我們要在演示示例的根文件夾目錄中創(chuàng)建解決方案,命令如下所示:
dotnet sln add ConsoleApp42/MyApp.sln

也可以使用 dotnet sln 命令刪除或列出解決方案中的項目。如果要添加或刪除對項目的引用,則需要使用 dotnet add 命令。我建議大家閱讀下 Jeremy Miller 的關于可擴展的 dotnet CLI 的文章以獲取更多詳細細節(jié),或者通過鍵入 dotnet help sln 或 dotnet help add 獲取。
添加另一個項目也非常簡單,但是我們必須以兩步的方式來完成:創(chuàng)建,然后添加。例如,可以將一個測試項目添加到解決方案中:
dotnet new nunitdotnet sln add Tests/MyAppTests.csproj

向項目添加新文件

向項目中添加新文件甚至更加容易,這主要歸功于.NET Core 對 MSBuild 文件的改進。我們不需要再在.csproj 文件中顯式地列出 C# 文件了,因為它們是通過通配符自動獲取的。我們只需要在文件夾中創(chuàng)建一個文件,它將自動成為項目的一部分。我們既可以手動也可以使用 dotnet new 提供模板文件來創(chuàng)建文件。
到模板,我們怎么知道有哪些可用的模板呢?如何區(qū)分項目模板( project template)和項模板(item template)呢?這是 dotnet new --list 的工作,它可以輸出所有可用的模板列表:
模板簡稱語言標簽
Console Application
console
[C#], F#, VB
Common/Console
Class library
classlib
[C#], F#, VB
Common/Library
Unit Test Project
mstest
[C#], F#, VB
Test/MSTest
NUnit 3 Test Project
nunit
[C#], F#, VB
Test/NUnit
NUnit 3 Test Item
nunit-test
[C#], F#, VB
Test/NUnit
xUnit Test Project
xunit
[C#], F#, VB
Test/xUnit
Razor Page
page
[C#]
Web/ASP.NET
MVC ViewImports
viewimports
[C#]
Web/ASP.NET
MVC ViewStart
viewstart
[C#]
Web/ASP.NET
ASP.NET Core Empty
web
[C#], F#
Web/Empty
ASP.NET Core Web App (Model-View-Controller)
mvc
[C#], F#
Web/MVC
ASP.NET Core Web App
razor
[C#]
Web/MVC/Razor Pages
ASP.NET Core with Angular
angular
[C#]
Web/MVC/SPA
ASP.NET Core with React.js
react
[C#]
Web/MVC/SPA
ASP.NET Core with React.js and Redux
reactredux
[C#]
Web/MVC/SPA
Razor Class Library
razorclasslib
[C#]
Web/Razor/Library/Razor Class Library
ASP.NET Core Web API
webapi
[C#], F#
Web/WebAPI
global.json file
globaljson

Config
NuGet Config
nugetconfig

Config
Web Config
webconfig

Config
Solution File
sln

Solution
上述列表列出了所有的模板。使用 --type 參數(shù)可以進行進一步的過濾,如使用 --type project、–type item 或–type other。項目模板將會創(chuàng)建一個項目,項模板將會創(chuàng)建一個文件,而其他模板僅對 sln 模板創(chuàng)建的解決方案文件有用。
這個列表中的簡稱(上表第 2 列)是調(diào)用 dotnet new 時使用的名稱(例如 dotnet new console、dotnet new classlib、dotnet new mvc 等)。有些模板支持多種語言,默認語言為方括號中的(劇透下,它們都是 C#)。我們可以使用 --language 選項來選擇不同的語言,但是要注意#符號!一些命令行 shell 將其視為注釋字符,使用–language F# 解析可能會失敗。這時可以通過引用值 -  “–language F#” 來處理。
最后,每個模板都有一個或多個標簽。這些標簽是一種對模板進行分類的方法,但目前它們并不是作為命令行工具的一部分被使用。但是,它們可以被其他宿主用于分組或過濾。是的,沒錯,dotnet new 模板引擎可以用于其他宿主,比如 IDE。稍后再詳細介紹。

自定義模板

到目前為止,我們只研究了一個非常簡單的 Hello World 控制臺應用程序,并添加了一些測試。讓我們看些更有趣的東西吧。假設要創(chuàng)建一個新的 ASP.NET 項目。查看上面的模板列表,我們有幾個選擇??梢詣?chuàng)建一個空的 web 項目、一個 MVC 項目、一個帶有 Angular 的項目或者一個帶有 React.js 的項目。但是這些都是相當嚴格的模板。我們能對這些模版進行定制嗎?好消息是:可以的。
模板可以接受一些變更生成內(nèi)容的參數(shù)。 – help 命令將會提供模板所理解的參數(shù)的詳細信息。讓我們從一個簡單的例子開始吧:
> dotnet new classlib
Class library (C
Author: Microsoft
Description: A project for creating a class library that targets .NET Standard or .NET Core
Options:
-f|
netcoreapp2.1 - Target netcoreapp2.1
netstandard2.0 - Target netstandard2.0
Default: netstandard2.0


bool - Optional
Default: false / (*) true


* Indicates the value used if the switch is provided without a value.
在此,我們可以看到 classlib 模板有兩個參數(shù):一個是 --framework,它用于指定要將什么目標框架寫入項目文件中;另一個是 --no-restore,它用于控制在創(chuàng)建項目時是否執(zhí)行 NuGet 還原。
web 模板也有類似的參數(shù),但是它們的數(shù)量比我們這里列出的要多得多。嘗試 dotnet new mvc --help 可以了解更多詳細信息。有些參數(shù)可以指定身份驗證類型、是否禁用 HTTPS、是否是使用 LocalDB 替換 SQLite 等等。這些參數(shù)中的每一個都會變更模板代碼的生成方式,它們有的是替換文件中的內(nèi)容,有的是根據(jù)需要包含或排除文件。
當我們討論幫助文檔時,有兩個非常有用的命令:dotnet help new,它將在 dotnet new 命令本身之上打開一個網(wǎng)頁;dotnet new {template} –help,它將顯示命名模板及其參數(shù)的幫助信息。

添加自定義模板

dotnet new 命令的真正強大之處在于添加新的自定義模板。更好的是,只需要將模版打包到一個 NuGet 包中并上傳到 nuget.org 上,即可實現(xiàn)模板的分發(fā)和共享。這使得開始使用一個框架或自動化創(chuàng)建新項目樣板或項目項樣板非常容易。
要添加一個新的自定義模板,使用 dotnet new --install {template} 命令,傳入一個 NuGet 包名或一個本地模板的文件目錄。但如何找到新的模板呢?
一種方法是搜索我們正在使用的框架,并查看它的模板是否可用,但這樣做容易出錯。幸運的是,我們可以訪問 dotnetnew.azurewebsites.net 并通過關鍵字搜索模板。網(wǎng)站上有超過 500 個模板,這使得它成為了一個很好的發(fā)現(xiàn)資源的地方。
例如,可以使用 dotnet new  --install Amazon.Lambda.Templates 為 AWS Lambda 項目安裝一組模板。通過 NuGet 包安裝模板有一個非常好的特性,那就是每個包可以包含多個模板。這個 AWS Lambda 包包含了 28 個不同的模板,并且還包括了一個教程項目。
當然,如果我們不想再使用某個模板了,只需要使用 dotnet new  --uninstall {package} 卸載它即可。這里傳遞的名稱是已安裝模板包的名稱,如果我們不確定對應的名稱,只需要運行 dotnet new --uninstall 即可獲得一個列表。

創(chuàng)建自己的模板

我們還可以創(chuàng)建自己的自定義模板。它們不一定是針對流行框架的,但可能是針對內(nèi)部或個人項目的。實際上,如果我們經(jīng)常要自己創(chuàng)建一個特定的文件夾目錄結構、引用集或樣板文件,那么可以考慮創(chuàng)建項目或項模板。項目模板只是簡單的純文本文件,包括 .csproj files (它們不要求生成的模板是特定于 .NET Core 的,并且它們可以用于任何框架。)。
創(chuàng)建一個新的模板是非常容易的,而且維護起來也很容易。傳統(tǒng)上,可以執(zhí)行文本替換的模板會使用一種特殊的語法,比如 VARIABLEVARIABLE 標記,該標記將在計算模板時被替換。不幸的是,這對于文件類型來說通常是無效的語法,文件類型會使得它無法通過運行項目來測試模板的正確性。這會導致 bug 并減緩迭代時間,基本上也會帶來一些維護上的麻煩。
幸運的是,模板引擎的設計者已經(jīng)考慮到了這一點,并且想出了一個更好的工作方式:運行模板。
想法很簡單:模板就是純文本文件。沒有特殊格式,也沒有特殊標記。所以, C# 文件始終是有效的 C#文件。如果某個模板想要替換某些文本,比如用基于項目名稱的命名空間替換 C# 命名空間,則可以使用簡單的搜索和替換來處理。例如,假設我們有一個這樣的模板:
namespace RootNamespace
{
public static class Main
{

}
}
模板的 JSON 配置定義了一個符號來替換命名空間。符號的值是基于項目名稱的,它可能應用了內(nèi)置轉換來確保它只包含有效的字符。這個符號還將定義它要替換的文本 “RootNamespace”。當模板引擎處理每個文件時,如果它看到 "RootNamespace",會用符號值將其替換。
這種簡單的搜索和替換通常是基于符號的,而符號又是基于參數(shù)的,例如模板名、輸出名或其他實際的自定義參數(shù)。但是,也可以基于生成器來創(chuàng)建符號,如創(chuàng)建 GUID、隨機數(shù)或當前時間戳等等。
但是,如果一個模版沒有條件代碼(根據(jù)參數(shù)添加或刪除的內(nèi)容),那么它是不完整的。dotnet new 是如何處理這個問題并將“運行模板”作為一個選項的呢?它實際上是在每個文件類型的基礎上處理的,內(nèi)置了一些默認配置,并且能夠為未知的文件格式定義自己的樣式。本質上,其思想是對那些支持它的文件類型使用特定于文件的預處理程序(例如,用于 C#或 C++ 的#if),對那些不支持它的文件類型使用特殊格式的注釋,比如 JSON。
cs
public class HomeController : Controller
{
public IActionResult Index() => View();

public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}

#if (EnableContactPage)
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
#endif

public IActionResult Error() => View();
}
模板的所有元數(shù)據(jù)都位于 template.json 文件中。它包括模板的簡稱、描述、作者、標簽和支持的語言。因為一個模板只能針對一種語言,所以它還包括一個“組標識”選項,當有多個模板時可以指定該選項,為每個模版指定一種語言。元數(shù)據(jù)文件還可以包括有關要復制或重命名文件的源和目標、條件文件副本、替換符號、命令行參數(shù)和創(chuàng)建后的操作(如包還原)等可選信息。但默認情況下,模板引擎將復制并處理模板文件結構中的所有文件。
{"author": "Matt Ellis","classifications": [ "Hello world" ],"name": "Hello world template","identity": "Matt.HelloWorldTemplate.CSharp","shortName": "helloworld","guids": [ "d23e3131-49a0-4930-9870-695e3569f8e6" ],"sourceName": "MyTemplate"}
template.json 文件必須放在模板文件夾結構的根目錄下,即位于一個名為 .template.config 的文件夾中。文件夾目錄結構的其余部分可以完全由我們來定:模板引擎在評估模板時將會保持相同的目錄結構。換句話說,如果我們將 README.md 文件添加到模板的根目錄中,那么當調(diào)用 dotnet new 時,模板引擎將會在輸出文件夾的根目錄中創(chuàng)建一個 README.md。所以,如果我們使用–output MyApp,將得到一個名為 MyApp/README.md 的文件。
> tree -a.├── .template.config│   └── template.json├── MyTemplate.csproj├── Program.cs└── Properties└── AssemblyInfo.cs
2 個目錄,4 個文件
要安裝和測試模板,只需要調(diào)用 dotnet new --install {template},就像安裝自定義模板一樣,但這一次是將路徑傳遞給模板文件夾結構的根目錄。如果要卸載,使用 dotnet new --uninstall {template}。同樣地,如果我們不確定要傳遞什么參數(shù),可以使用 dotnet new --uninstall 來獲取完整的列表。

分發(fā)模板

一旦我們的模板準備就緒,可以分發(fā)了,就可以把它打包成一個 NuGet 包并上傳到 nuget.org 上。我們需要像往常一樣創(chuàng)建一個 .nuspec 文件,但是需要做兩個小的調(diào)整:添加一個 packageType 元素并將 name 屬性設置為“Template”,然后確保模板文件夾結構被復制到一個名為“content”的文件夾中。
<package>

  <metadata>

    <id>MattDemo.HelloWorldTemplate</id>

    <version>1.0</version>

    <authors>Matt Ellis</authors>

    <description>Hello World template</description>

    <packageTypes>

      <packageTypename="Template"/>

    </packageTypes>

  </metadata>

  <files>

    <filesrc=".template.config/template.json"target="content/.template.config"/>

    <filesrc="MyTemplate.csproj"target="content/"/>

    <filesrc="Program.cs"target="content/"/>

    <filesrc="Properties/*"target="content/Properties/"/>

  </files>

</package>
此外,可以在一個包中包含多個模板:只需在“content”下創(chuàng)建多個文件夾,并為每個模板添加一個 .tempate.config/template.json 即可。
在 template.json 文件中還有更多的選項和功能,但是涵蓋所有選項和功能超出了本文的范圍。不過,基于我們這里討論的這些內(nèi)容,也可以看出模板引擎是非常強大、靈活的,并且它使用起來相當簡單。請查看微軟文檔網(wǎng)站和 dotnet/templating Github 上的 Wiki 了解更多內(nèi)容。

模板引擎

dotnet new 最有趣的一點是,它被設計成可以在多個宿主上使用。dotnet new CLI 工具只是其中的一個宿主 :模板引擎本身也可以用作其他應用程序的 API。對于那些喜歡使用 IDE 而不是命令行的人來說,這是非常好的,但是他們?nèi)匀幌M軌蜉p松地添加自定義項目模板,而這在 IDE 中并不總是那么容易。
我們可以在 JetBrains Rider 中看到這一點?!靶陆椖俊睂υ捒蛴赡0逡?API 來提供支持,其中列出了所有可用的模板,甚至包括自定義模板。當用戶想要創(chuàng)建一個項目時,模板引擎用于生成文件。
如果仔細觀察,我們會發(fā)現(xiàn) Rider 的模版比 .NET CLI 的要多。這是因為 Rider 提供了額外的模板來支持 .NET 框架和 Xamarin 項目。模板引擎 API 允許宿主將模板安裝到一個自定義的位置,并且可以從這兩個位置拿到模板列表,這意味著 Rider 將顯示由 dotnet new --install 安裝的自定義模板,以及使用“新建項目”對話框的“更多模板”頁中的安裝按鈕。重新加載后,新模板將與所有其他模板一樣顯示在列表中。

輕松創(chuàng)建自定義的新項目

dotnet new 命令使得創(chuàng)建新項目和項目項變得很容易。默認模板集將幫助我們快速構建基于命令行或 ASP.NET 的 .NET Core 應用程序,并且有助于創(chuàng)建測試項目和其他基于.NET 語言的目標項目。我們可以很容易地安裝自定義模板來創(chuàng)建具有其他要求的項目,例如不同的文件夾結構或框架依賴關系。自定義模板的格式使我們可以輕松地創(chuàng)建自己的模板,它雖然利用替換變量和條件代碼,但仍能保持模板項目的可編譯性和可維護性。與 dotnet sln 命令以及其他可擴展的 dotnet CLI 命令一起使用,new 模板引擎使創(chuàng)建和管理項目、項目項和解決方案變得更加容易,并且它可以跨平臺、直接利用命令行進行創(chuàng)建。


聲明:
本文于網(wǎng)絡整理,版權歸原作者所有,如來源信息有誤或侵犯權益,請聯(lián)系我們刪除或授權事宜。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多