Netcore【】
2023-01-10 19:41:21財(cái)都小生正文
關(guān)鍵要點(diǎn)dotnet cli 使得基于. Net 項(xiàng)目的自動(dòng)化和腳本編寫(xiě)變得非常簡(jiǎn)單,尤其是與十多年前的. Net 技術(shù)相比。dotnet cli 可擴(kuò)展性模型創(chuàng)造了條件,使得通過(guò) Nuget 將外部.NET 編寫(xiě)的命令行程序集成到你的自動(dòng)化構(gòu)建中成為可能。dotnet cli 允許在你的構(gòu)建腳本中針對(duì)解決方案進(jìn)行測(cè)試。dotnet cli 的測(cè)試輸出有助于更好地使用持續(xù)集成 (CI)。使用 Docker 之類的容器技術(shù)比使用 dotnet cli 要容易得多。
隨著.NET Core 2.0 的發(fā)布,微軟擁有了通用、模塊化、跨平臺(tái)和開(kāi)源平臺(tái)的下一個(gè)主要版本,該版本最初于 2016 年發(fā)布。.NET Core 已經(jīng)創(chuàng)建了許多 API,這些 API 在.NET 框架的當(dāng)前版本中是可用的。它最初是為了下一代 ASP.NET 解決方案創(chuàng)建的,但現(xiàn)在是許多其他場(chǎng)景的驅(qū)動(dòng)和基礎(chǔ),包括物聯(lián)網(wǎng)、云和下一代移動(dòng)解決方案。在關(guān)于.NET Core 的第二個(gè)系列的文章中,我們將進(jìn)一步探討.NET Core 的優(yōu)點(diǎn),以及它如何不僅有益于傳統(tǒng)的.NET 開(kāi)發(fā)人員,也有益于所有需要為市場(chǎng)提供強(qiáng)健的、高效的和經(jīng)濟(jì)的解決方案的技術(shù)人員。
最近總有人問(wèn)我,和那些要么遲疑,要么不能退出舊版本、全功能的.NET 的人相比,選擇.NET Core 的優(yōu)勢(shì)是什么?我在回答中會(huì)提到.NET Core 有更好的性能、改進(jìn)的 csproj 文件格式、改進(jìn)的 ASP 可測(cè)試性,并且它是跨平臺(tái)的。
作為幾個(gè) OSS 工具 (Marten、StructureMap,以及在這個(gè)項(xiàng)目中作為例子被引用的Alba) 的作者,對(duì)我個(gè)人而言最大的優(yōu)勢(shì)可能是dotnet cli的出現(xiàn)。我個(gè)人認(rèn)為,結(jié)合新的.NET SDK csproj文件格式一起使用時(shí),dotnet cli 工具使我可以更容易創(chuàng)建項(xiàng)目和維護(hù)構(gòu)建腳本。我可以更容易在構(gòu)建腳本中運(yùn)行測(cè)試,更容易使用和分發(fā) Nuget 包,cli 可擴(kuò)展性機(jī)制非常適合將通過(guò) Nuget 包分發(fā)的自定義可執(zhí)行文件合并到自動(dòng)構(gòu)建中。
若要開(kāi)始使用 dotnet cli,首先要在開(kāi)發(fā)機(jī)器上安裝.NET SDK。安裝完成后,給你一些有用的提示:將“dotnet”工具全局安裝到你的 PATH 中,這樣在任何地方都可以通過(guò)命令行提示符使用它。dotnet cli 采用 Linux 風(fēng)格的命令語(yǔ)法,用“–word [value]”這種普通寫(xiě)法表示選擇的參數(shù),或者直接用縮寫(xiě)形式“-w [value]”。如果您習(xí)慣 Git 或 Node.js 命令行工具,就不會(huì)對(duì) dotnet cli 感到陌生。“dotnet --help”將列出已安裝的命令和一些基本語(yǔ)法用法。“dotnet --info”將告訴你使用的是哪個(gè)版本的 dotnet cli。在持續(xù)集成構(gòu)建中調(diào)用此命令可能是一個(gè)好主意,以便在本地工作并在構(gòu)建服務(wù)器失敗時(shí)排除故障,反之亦然。盡管我在本文中討論的是.NET Core,但是請(qǐng)注意,你可以在完整.NET 框架的以前版本中使用新的 SDK 項(xiàng)目格式和 dotnet cli。
命令行中的 Hello World
為了簡(jiǎn)單了解一下 dotnet cli 的一些亮點(diǎn),讓我們假設(shè)想構(gòu)建一個(gè)簡(jiǎn)單的“Hello World”ASP.NET Core 應(yīng)用程序。不過(guò),為了好玩,我們來(lái)添加一些新花樣:
1. 我們的 web 服務(wù)將在一個(gè)單獨(dú)的項(xiàng)目中進(jìn)行自動(dòng)化測(cè)試。
2. 我們將通過(guò) Docker 容器部署我們的服務(wù),因?yàn)檫@是很酷的做法 (它展示了更多的 dotnet cli)。
3. 當(dāng)然,我們將盡可能多地使用 dotnet cli。
如果您想看到這段代碼的最終結(jié)果,請(qǐng)查看this GitHub repository。
首先,讓我們從一個(gè)名為“DotNetCliArticle”的空目錄開(kāi)始,并打開(kāi)您最喜歡的命令行工具到該目錄。我們將從使用“dotnet new”命令來(lái)生成解決方案文件和新項(xiàng)目開(kāi)始。.NET SDK 附帶了幾個(gè)用于創(chuàng)建常見(jiàn)項(xiàng)目類型或文件的通用模板,以及其他可作為外接程序使用的模板 (稍后部分將對(duì)此進(jìn)行詳細(xì)介紹)。要查看在你的機(jī)器上可用的模板,可以使用以下命令 dotnet new -help,它應(yīng)該會(huì)給出如下輸出:
你可能會(huì)留意到有一個(gè) sln 模板,它針對(duì)的是空解決方案文件。我們將使用該模板,鍵入 dotnet new sln 命令,該命令將生成以下輸出:
復(fù)制代碼
The template "Solution File" was created successfully.
默認(rèn)情況下,此命令將以包含的目錄命名解決方案文件。因?yàn)槲覍⒏夸浢麨闉椤癉otNetCliArticle”,所以生成的解決方案文件是“DotNetCliArticle.sln”。
接下來(lái),讓我們用以下命令添加“Hello,World”的實(shí)際項(xiàng)目:
復(fù)制代碼
dotnet new webapi --output HeyWorld
上面的命令意思是將“webapi”模板用到通過(guò)“output”參數(shù)選擇的“HeyWorld”中。這個(gè)模板將生成一個(gè)精簡(jiǎn)的 MVC Core 項(xiàng)目結(jié)構(gòu),適合于無(wú)頭 API。同樣,默認(rèn)的做法是根據(jù)所在的目錄命名項(xiàng)目文件,因此我們?cè)谀夸浵碌玫揭粋€(gè)名為“HeyWorld.csproj”的文件,以及所有基本文件,組成一個(gè)最小的 ASP.NET MVC Core API 項(xiàng)目。該模板還設(shè)置了所有必要的 Nuget 對(duì) ASP.NET Core 的引用,我們?cè)谛马?xiàng)目啟動(dòng)時(shí)會(huì)用到它們。
由于我剛好在一個(gè)小型 Git 存儲(chǔ)庫(kù)中構(gòu)建了它,在使用 Git add 添加了任何新文件之后,我使用 Git status 查看新創(chuàng)建的文件:
復(fù)制代碼
new file: HeyWorld/Controllers/ValuesController.cs new file: HeyWorld/HeyWorld.csproj new file: HeyWorld/Program.cs new file: HeyWorld/Startup.cs new file: HeyWorld/appsettings.Development.json new file: HeyWorld/appsettings.json
現(xiàn)在,要將新項(xiàng)目添加到我們的空解決方案文件中,您可以像這樣使用“dotnet sln”命令:
復(fù)制代碼
dotnet sln DotNetCliArticle.sln add HeyWorld/HeyWorld.csproj
現(xiàn)在我們有了一個(gè)新的 ASP.NET Core API 服務(wù)作為外殼,無(wú)需打開(kāi) Visual Studio.NET(或者是 JetBrains Rider)。為了更進(jìn)一步,在編寫(xiě)任何實(shí)際代碼之前啟動(dòng)我們的測(cè)試項(xiàng)目,我發(fā)出以下命令:
復(fù)制代碼
dotnet new xunit --output HeyWorld.Testsdotnet sln DotNetCliArticle.sln add HeyWorld.Tests/HeyWorld.Tests.csproj
上面的命令使用 xUnit.NET 創(chuàng)建一個(gè)新項(xiàng)目,并將該新項(xiàng)目添加到我們的解決方案文件中。測(cè)試工程需要對(duì)“HeyWorld”的工程引用,幸運(yùn)的是,我們可以使用很棒的“dotnet add”工具添加工程引用,如下所示:
復(fù)制代碼
dotnet add HeyWorld.Tests/HeyWorld.Tests.csproj reference HeyWorld/HeyWorld.csproj
在打開(kāi)解決方案之前,我知道還有一些 Nuget 參考資料,我想在測(cè)試項(xiàng)目中使用它們。我選擇的斷言工具是Shoully,因此我將通過(guò)對(duì)命令行發(fā)出另一個(gè)調(diào)用來(lái)添加對(duì)最新版本的 shoully 的引用:
復(fù)制代碼
dotnet add HeyWorld.Tests/HeyWorld.Tests.csproj package Shouldly
命令行的輸出如下:
復(fù)制代碼
info : Adding PackageReference for package 'Shouldly' into project 'HeyWorld.Tests/HeyWorld.Tests.csproj'.log : Restoring packages for /Users/jeremydmiller/code/DotNetCliArticle/HeyWorld.Tests/HeyWorld.Tests.csproj...info : GET https://api.nuget.org/v3-flatcontainer/shouldly/index.jsoninfo : OK https://api.nuget.org/v3-flatcontainer/shouldly/index.json 109msinfo : Package 'Shouldly' is compatible with all the specified frameworks in project 'HeyWorld.Tests/HeyWorld.Tests.csproj'.info : PackageReference for package 'Shouldly' version '3.0.0' added to file '/Users/jeremydmiller/code/DotNetCliArticle/HeyWorld.Tests/HeyWorld.Tests.csproj'.
接下來(lái),我想向名為 Alba 的測(cè)試項(xiàng)目添加至少一個(gè) Nuget 引用。我將使用AspNetCore2來(lái)編寫(xiě)針對(duì)新的 web 應(yīng)用程序的 HTTP 契約測(cè)試:
復(fù)制代碼
dotnet add HeyWorld.Tests/HeyWorld.Tests.csproj package Alba.AspNetCore2
現(xiàn)在,在使用代碼之前先檢查一下,我將在命令行發(fā)出以下命令構(gòu)建解決方案中的所有項(xiàng)目,確保它們都可以正常編譯:
復(fù)制代碼
dotnet build DotNetCliArticle.sln
由于 Alba.AspNetCore2 和 ASP.NET Core Nuget 在 HeyWorld 項(xiàng)目中的引用之間的菱形依賴版本的沖突,所以沒(méi)有編譯。不過(guò)不用擔(dān)心,因?yàn)檫@個(gè)問(wèn)題很容易解決,只需修復(fù) Microsoft.AspNetCore 的版本依賴關(guān)系即可。測(cè)試項(xiàng)目中的所有 Nuget 都是這樣的:
復(fù)制代碼
dotnet add HeyWorld.Tests/HeyWorld.Tests.csproj package Microsoft.AspNetCore.All --version 2.1.2
在上面的示例中,使用值為“2.1.2”的“–version”標(biāo)志將修復(fù)對(duì)該版本的引用,而不僅僅是使用從 Nuget 提要中找到的最新版本。
為了再次檢查我們的 Nuget 依賴問(wèn)題是否已經(jīng)解決,我們可以使用下面的命令進(jìn)行檢查,它比重新編譯所有東西要更快:
復(fù)制代碼
dotnet clean && dotnet restore DotNetCliArticle.sln
作為一個(gè)有經(jīng)驗(yàn)的.NET 開(kāi)發(fā)人員,我非常擔(dān)心臨時(shí) /obj 和 /bin 文件夾中殘留的文件。因此,我在 Visual Studio 中使用“Clean Solution”命令,以防我試圖改變引用的時(shí)候落下些什么。從命令行執(zhí)行“dotnet clean”命令是完全相同的操作。
同樣,針對(duì)眾所周知的 Nuget 依賴問(wèn)題,“dotnet restore”命令在解決方案中都試著去解決了。在這種情況下,使用“dotnet restore”可以讓我們快速發(fā)現(xiàn)任何潛在的沖突或丟失的 Nuget 引用,而無(wú)需進(jìn)行完整的編譯,我在自己的工作中主要就采用該命令。在最新版本的 dotnet cli 中,在調(diào)用“dotnet build/test/pack/etc”時(shí),會(huì)自動(dòng)為您完成 Nuget 解析 (該行為可以用標(biāo)記覆蓋),這將首先需要 Nuget。
我們調(diào)用的“dotnet restore DotNetCliArticle.sln”干凈利落地運(yùn)行完畢,沒(méi)有錯(cuò)誤,所以我們終于可以準(zhǔn)備編寫(xiě)一些代碼了。讓我們打開(kāi)您選擇的 C# 編輯器,向 HeyWorld 添加一個(gè)代碼文件。測(cè)試項(xiàng)目包含一個(gè)非常簡(jiǎn)單的 HTTP 協(xié)議測(cè)試,它將指定我們希望從新的 HeyWorld 應(yīng)用程序中的“GET: /”路由獲得的行為:
復(fù)制代碼
using System.Threading.Tasks;using Alba;using Xunit;namespace HeyWorld.Tests{ public class verify_the_endpoint { [Fact] public async Task check_it_out() { using (var system = SystemUnderTest.ForStartup<Startup>()) { await system.Scenario(s => { s.Get.Url("/"); s.ContentShouldBe("Hey, world."); s.ContentTypeShouldBe("text/plain; charset=utf-8"); }); } } }}
結(jié)果文件應(yīng)該保存在具有適當(dāng)名稱 (如 verify_the_endpoints.cs) 的 HeyWorld.Tests 目錄。
在沒(méi)有深入了解 Alba 機(jī)制前,我們的新 HeyWorld 應(yīng)用的首頁(yè)路由應(yīng)該寫(xiě)出“Hey, world”。雖然我們還沒(méi)有在 HeyWorld 應(yīng)用中編寫(xiě)任何實(shí)際的代碼,但是我們?nèi)匀豢梢赃\(yùn)行這個(gè)測(cè)試,看看它能夠連接正確,還是因?yàn)槟承袄硭?dāng)然的理由”而失敗。
回到命令行,我可以使用以下命令運(yùn)行測(cè)試項(xiàng)目中的所有測(cè)試:
復(fù)制代碼
dotnet test HeyWorld.Tests/HeyWorld.Tests.csproj
我們的一個(gè)測(cè)試會(huì)失敗,因?yàn)檫€沒(méi)有實(shí)現(xiàn)任何東西,它給了我們這樣的輸出:
復(fù)制代碼
Build started, please wait...Build completed.Test run for /Users/jeremydmiller/code/DotNetCliArticle/HeyWorld.Tests/bin/Debug/netcoreapp2.1/HeyWorld.Tests.dll(.NETCoreApp,Version=v2.1)Microsoft (R) Test Execution Command Line Tool Version 15.7.0Copyright (c) Microsoft Corporation. All rights reserved.Starting test execution, please wait...Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.Test Run Successful.Test execution time: 2.4565 Seconds
為了把輸出求和,執(zhí)行了一個(gè)測(cè)試,但是失敗了。我們還可以看到標(biāo)準(zhǔn)的 xUnit 輸出,它提供了一些關(guān)于測(cè)試失敗原因的信息。這里需要注意的是,“dotnet test”命令將返回一個(gè)退出代碼,如果所有測(cè)試都通過(guò),則返回 0,表示成功;如果任何測(cè)試失敗,則返回一個(gè)非零退出代碼,表示失敗。這對(duì)于持續(xù)集成 (CI) 腳本非常重要,大多數(shù) CI 工具使用任何命令的退出代碼來(lái)確定構(gòu)建何時(shí)失敗。
我認(rèn)為上面的測(cè)試之所以失敗是因?yàn)椤袄硭?dāng)然的原因”,這意味著測(cè)試工具似乎能夠引導(dǎo)真正的應(yīng)用程序,我希望得到 404 響應(yīng),因?yàn)檫€沒(méi)有編寫(xiě)任何代碼。接下來(lái),讓我們?yōu)轭A(yù)期的行為實(shí)現(xiàn)一個(gè) MVC Core 端點(diǎn):
復(fù)制代碼
public class HomeController : Controller{ [HttpGet("/")] public string SayHey() { return "Hey, world!"; }}
(注意,前面的代碼應(yīng)該作為 HeyWorldstartup.cs 文件中的附加類添加)
再次回到命令行,讓我們運(yùn)行前面的“dotnet test HeyWorld.Tests/HeyWorld.Tests.csproj”命令,希望看到這樣的結(jié)果:
復(fù)制代碼
Build started, please wait...Build completed.Test run for /Users/jeremydmiller/code/DotNetCliArticle/HeyWorld.Tests/bin/Debug/netcoreapp2.1/HeyWorld.Tests.dll(.NETCoreApp,Version=v2.1)Microsoft (R) Test Execution Command Line Tool Version 15.7.0Copyright (c) Microsoft Corporation. All rights reserved.Starting test execution, please wait...Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.Test Run Successful.Test execution time: 2.4565 Seconds
好了,現(xiàn)在測(cè)試通過(guò)了,讓我們運(yùn)行實(shí)際的應(yīng)用程序。由于“dotnet new webapi”模板使用進(jìn)程內(nèi)的 in-process Kestrel web server 來(lái)處理 HTTP 請(qǐng)求,所以要運(yùn)行新的 HeyWorld 應(yīng)用程序,我們唯一需要做的一件事就是從命令行使用以下命令啟動(dòng)它:
復(fù)制代碼
dotnet run --project HeyWorld/HeyWorld.csproj
運(yùn)行上面的命令應(yīng)該會(huì)得到如下輸出:
復(fù)制代碼
Using launch settings from HeyWorld/Properties/launchSettings.json...: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]User profile is available. Using '/Users/jeremydmiller/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.Hosting environment: DevelopmentContent root path: /Users/jeremydmiller/code/DotNetCliArticle/HeyWorldNow listening on: https://localhost:5001Now listening on: http://localhost:5000Application started. Press Ctrl C to shut down.
要測(cè)試我們現(xiàn)在正在運(yùn)行的新應(yīng)用程序,只需在瀏覽器中導(dǎo)航如下:
處理 HTTPS 設(shè)置超出了本文的范圍。
請(qǐng)?jiān)俅巫⒁猓壹僭O(shè)所有命令都是在將當(dāng)前目錄設(shè)置為解決方案根文件夾的情況下執(zhí)行的。如果當(dāng)前目錄是一個(gè)項(xiàng)目目錄,并且只有一個(gè) *.csproj。那么,您只需在該目錄下鍵入“dotnet run”即可。現(xiàn)在我們已經(jīng)有了一個(gè)經(jīng)過(guò)測(cè)試的 web api 應(yīng)用程序,接下來(lái)讓我們將 HeyWorld 放到 Docker 鏡像中。使用 the standard template for dockerizing a .NET Core application,我們將向 HeyWorld 項(xiàng)目添加一個(gè) Dockerfile,內(nèi)容如下:
復(fù)制代碼
FROM microsoft/dotnet:sdk AS build-envWORKDIR /appCopy csproj and restore as distinct layersCOPY *.csproj ./RUN dotnet restoreCopy everything else and buildCOPY . ./RUN dotnet publish -c Release -o outBuild runtime imageFROM microsoft/dotnet:aspnetcore-runtimeWORKDIR /appCOPY --from=build-env /app/out .ENTRYPOINT ["dotnet", "HeyWorld.dll"]
(注意,前面的文本應(yīng)該保存到項(xiàng)目目錄中名為 Dockerfile 的文本文件中——在本例中是 HeyWorldDockerfile)。
因?yàn)檫@篇文章僅僅是關(guān)于 dotnet cli 的,我只想關(guān)注 Dockerfile 中它的兩種用法:
1.“dotnet restore”–正如我們?cè)谏厦鎸W(xué)到的,這個(gè)命令將解決應(yīng)用程序的任何 Nuget 依賴關(guān)系。
2.“dotnet publish -c Release -o out”–“dotnet publish”命令將構(gòu)建指定的項(xiàng)目,并將組成應(yīng)用程序的所有文件復(fù)制到給定位置。在我們的例子中,“dotnet publish”將為 HeyWorld 本身復(fù)制已編譯的程序集、從 Nuget 依賴項(xiàng)引用的所有程序集、配置文件以及 csproj 文件中引用的任何文件。
請(qǐng)注意,在上面的用法中,我們必須通過(guò)使用“-c Release”標(biāo)志明確地告知“dotnet publish”用“Release”配置編譯。那些用于編碼的 dotnet cli 命令 (例如“build”、“publish”、“pack”)如果沒(méi)有指定,將以 “Debug”為默認(rèn)值。注意這種行為,如果要發(fā)布用于生產(chǎn)的 Nuget 或應(yīng)用程序,請(qǐng)記住指定“-c Release”或“-configuration Release”。別怪我沒(méi)提醒你。
為了完成整個(gè)周期,我們現(xiàn)在可以使用以下命令通過(guò) Docker 構(gòu)建和部署我們的小 HeyWorld 應(yīng)用程序:
復(fù)制代碼
docker build -t heyworld .docker run -d -p 8080:80 --name myapp heyworld
第一個(gè)命令為我們的應(yīng)用程序“heyworld”構(gòu)建并本地發(fā)布 Docker 鏡像。第二個(gè)命令實(shí)際上作為一個(gè)名為“myapp”的 Docker 容器運(yùn)行我們的應(yīng)用程序。您可以打開(kāi)瀏覽器訪問(wèn)“http://localhost:8080”予以驗(yàn)證。
總結(jié)
dotnet cli 使得基于. NET 項(xiàng)目的自動(dòng)化和腳本編寫(xiě)變得非常簡(jiǎn)單,尤其是與十多年前的.NET 技術(shù)相比。在許多情況下,您甚至可能會(huì)避開(kāi)任何基于任務(wù)的構(gòu)建腳本工具 (Cake、Fake、Rake、Psake 等),而選擇只委托給 dotnet cli 的簡(jiǎn)單 shell 腳本。此外,dotnet cli 可擴(kuò)展性模型可以很容易地將外部.NET 授權(quán)的命令行應(yīng)用程序通過(guò) Nuget 分布到自動(dòng)構(gòu)建程序中。
關(guān)于作者杰里米·米勒 (Jeremy Miller)在密蘇里州一個(gè)農(nóng)場(chǎng)社區(qū)長(zhǎng)大,那里有一群“特別”的人,名叫“樹(shù)蔭技工”。通常,他們不是世界上最有名望的人,但他們有解決機(jī)械問(wèn)題的訣竅,而且做事魯莽無(wú)畏。如果你發(fā)現(xiàn)從一輛停在街區(qū)的通勤車下伸出來(lái)兩條腿,那他想必就是名修理工了,他的周圍是一些骨架車,堆擠在他那長(zhǎng)滿灌木、堆滿垃圾的院子里。你看到的被遺棄在他周圍的打漿機(jī)并不是沒(méi)用的,他們是素材。他會(huì)零零碎碎地進(jìn)行些小調(diào)整,然后根據(jù)你的需要想出一個(gè)創(chuàng)造性的解決方案。盡管名聲一般,但一個(gè)樹(shù)蔭技工知道如何讓東西運(yùn)行。雖然米勒沒(méi)有任何特殊的機(jī)械能力 (盡管他擁有機(jī)械工程學(xué)位),但他喜歡把自己當(dāng)成一個(gè)像樹(shù)蔭技工似的開(kāi)發(fā)人員。他的硬盤上肯定到處都是廢棄的開(kāi)源項(xiàng)目碎片。隨著.NET Core 2.0 的發(fā)布,微軟擁有了通用、模塊化、跨平臺(tái)和開(kāi)源平臺(tái)的下一個(gè)主要版本,該版本最初于 2016 年發(fā)布。.NET Core 已經(jīng)創(chuàng)建了許多 API,這些 API 在.NET 框架的當(dāng)前版本中是可用的。它最初是為了下一代 ASP.NET 解決方案創(chuàng)建的,但現(xiàn)在是許多其他場(chǎng)景的驅(qū)動(dòng)和基礎(chǔ),包括物聯(lián)網(wǎng)、云和下一代移動(dòng)解決方案。在關(guān)于.NET Core 的第二個(gè)系列的文章中,我們將進(jìn)一步探討.NET Core 的優(yōu)點(diǎn),以及它如何不僅有益于傳統(tǒng)的.NET 開(kāi)發(fā)人員,也有益于所有需要為市場(chǎng)提供強(qiáng)健的、高效的和經(jīng)濟(jì)的解決方案的技術(shù)人員。

