.NET Core系列 : 1、.NET Core 環境搭建和命令行CLI入門 介紹了.NET Core環境,本文介紹.NET Core中最重要的一個配置文件project.json的相關內容。我們可以使用.NET Core 的dotnet 命令行接口(CLI)dotnet new命令創建一個應用,也可以用Visual Studio 2015 update 3創建一個應用,他們都有一個project.json ,它是項目的配置文件,類似之前的*.csrpoj文件。Project.json 是一個新的項目文件,它的功能大部分與 *.*PROJ 文件重疊。它可標識項目引用、版本選項(如版本號)等事項,并可標識要編譯的平臺,例如,是 .NET Core 還是 .NET Framework。心細的你可能已經發現了他們所創建出來的project.json 文件的內容有很多都不一樣。我們下面就來看下這個文件的內容,project.json 的官方文檔 https://docs.microsoft.com/en-us/dotnet/articles/core/tools/project-json 。
project.json
首先,從我們 通過 Visual Studio 創建的項目 xproj 的 project.json︰
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
},
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
}
}
dotnet new 命令創建項目的 project.json:
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
},
"imports": "dnxcore50"
}
}
}
他們結構上看是相似的,但是具體內容上有很大的不同的地方,他們都有4個頂級的屬性:version, buildOptions, dependencies 和 framework。.NET Core 項目結構中最重要的文件可能是 project.json。此文件旨在:
替換 NuGet 文件管理器 package.config 文件,它可標識項目的 NuGet 引用。
指定項目支持的框架,以及有關如何為特定框架構建項目的配置詳細信息。
標識獨立應用的目標平臺,它含有其所有依賴項,包括對應平臺所需的特定于平臺的 .NET Core 運行時。或者,如果項目是可移植應用,project.json 可標識項目會在目標計算機(將在其上運行程序集)上安裝的框架。
這三個任務分布在 project.json 中的四個主要部分(根據項目類型,我將Frameworks 和 dependencies合并為功能重疊):
Version
version 這個屬性是你所要構建的組件的最小的元數據,其他元數據包括name,title,description ,copyright 等, name 選項默認情況下使用的是父文件夾名稱,你可以通過name 這個屬性給它取個你想要的名字。
buildOptions
buildOptions節點定義了如何編譯和編譯哪些文件等,也就是編譯選項。編譯選項部分包含一些有用的屬性。首先是 emitEntryPoint,這用來確定是否生成可執行二進制文件或 exe 。默認情況下,調用 Program.Main() 方法將被調用來運行你的應用。
我發現一個有趣的屬性是"debugType":"portable"。Visual Studio 代碼調試器必須設置這個屬性才能夠工作的。但這也意味著您的應用程序將以不同的方式發布,具體哪個值取決于您在此處的設置。簡要的可以看前一篇文章的dotnet publish 節,更多的介紹在后面發布應用程序的時候介紹。
Frameworks 和 dependencies
dependencies此部分列出了你的項目所依賴的各個 NuGet 包,包括所述依賴項的版本號。可以使用通配符指定版本號,從而你可以允許 NuGet 包管理器還原自動下載與通配符相匹配的“最新版本”。版本號的空引號對表示“使用最新可用項”。我們創建的項目可以針對一個或者多個Framework(比如我們希望創建的可以同時在.NET Framework和.NET Core上運行),支持的Framework定義在frameworks節點下。如果添加了多個Framework,并不是說最終生成的應用可以同時在這 些Framework中運行,而是說源文件在編譯的時候會針對這些Framework生成對應的程序集。對于傳統的.NET項目來說,如果我們需要調用某個API,需要添加所在程序集的引用。對于.NET Core來說,所有使用到的程序集都被打包成一個NuGet包,所以針對程序集的直接依賴轉變成針對某個NuGet包的依賴。針對NuGet的依賴主要有 兩種類型,一種是針對所有Framework的,它們會直接定義在dependencies節點下,另一種則是針對某個具體Framework的, 定義為當前Framework節點下的dependencies子節點。對于獨立應用,運行時部分指定將支持的 OS,因此可指定要綁定到應用程序的運行時庫。
從上面2個project.json 文件可以看出Frameworks 和 dependencies 存在依賴關系。他們是可以嵌套的,在最高一級的依賴項,將是所有的Frameworks所依賴的,也可以針對一個具體的Framework 構建它的依賴關系,不同的Framework使用不同版本的依賴項。看上面的例子,我們看到Visual Studio和dotnet CLI版本定義的是相同的結果,只是兩種不同的表達方式。
Microsoft.NETCore.App
我們來仔細看下 Microsoft.NETCore.App
:
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
這是一個依賴項,平臺的依賴,它也是Nuget包,其中包含了一堆系統庫的NuGet程序包,包含.netcore的基礎運行時和基礎類庫。 文章
Running .NET Core apps on multiple frameworks and What the Target Framework Monikers (TFMs) are about 詳細的介紹了具體的內容。
netcoreapp1.0
我們再來仔細看下 netcoreapp1.0
:
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
}
框架netcoreapp1.0 是個多目標框架對象名字(TFM)值,除了有經典的net45,net46,現在又有了一些新的像netcoreapp1.0,文章
NETStandard.Library
上面我們創建的項目是個應用程序,當我們回到類庫的時候,在依賴項里會發現一個NETStandard.Library:
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable"
},
"dependencies": {},
"frameworks": {
"netstandard1.6": {
"dependencies": {
"NETStandard.Library": "1.6.0"
}
}
}
}
這也是一個NuGet 程序包: https://www.nuget.org/packages/NETStandard.Library/,里面包含了多個目標版本,類似于老的PCL方法,以后就使用NETStandard.Library替代了PCL,我們有了一個更加統一的版本控制策略。
本質上來說,NETStandard.Library 是一個目標最低支持基礎類庫,這樣就可以更好的向前兼容性,在現有的平臺出現新的版本時(如.net core 1.1 甚至 2.0)而無需重新發布新的變化。具體參考 https://github.com/dotnet/corefx/blob/master/Documentation/architecture/net-platform-standard.md ,目前最新的表格:
Target Platform Name | Alias | |||||||
---|---|---|---|---|---|---|---|---|
.NET Platform Standard | netstandard | 1.0 | 1.1 | 1.2 | 1.3 | 1.4 | 1.5 | 1.6 |
.NET Core | netcoreapp | → | → | → | → | → | → | 1.0 |
.NET Framework | net | → | → | → | → | → | → | 4.6.3 |
→ | → | → | → | → | 4.6.2 | |||
→ | → | → | → | 4.6.1 | ||||
→ | → | → | 4.6 | |||||
→ | → | 4.5.2 | ||||||
→ | → | 4.5.1 | ||||||
→ | 4.5 | |||||||
Universal Windows Platform | uap | → | → | → | → | 10.0 | ||
Windows | win | → | → | 8.1 | ||||
→ | 8.0 | |||||||
Windows Phone | wpa | → | → | 8.1 | ||||
Windows Phone Silverlight | wp | 8.1 | ||||||
8.0 | ||||||||
Mono/Xamarin Platforms | → | → | → | → | → | → | * | |
Mono | → | → | * |
如何理解這個表格
- 如果一個類庫指定.NET平臺標準1.3版本,那么它僅能夠運行在.NET Framework 4.6或更新的框架、Universal Windows Platform 10(UWP)、DNX Core 5.0和Mono/Xamarin這些平臺上。
- 如果一個類庫指定.NET平臺標準1.3版本,那么它能夠引用(原文:consume)所有來自之前的.NET平臺標準的版本(1.2、1.1、1.0)。
關于project.json 的更多信息
.NET Core項目依賴全部使用NuGet,要求使用NuGet 3.0版本,默認使用nuget.org 作為源。在安裝VS2015 Update3時,.NET Core所需的官方依賴包都已經安裝在了(默認安裝)C:\Program Files (x86)\Microsoft SDKs\NuGetPackages目錄下,在nuget管理中也可以看到這是默認的離線包目錄,我們需要什么樣的包只要把它復制到這個目錄,在nuget管理中的程序包源選擇離線的源即可。執行dotnet restore命令后項目會根據project.json文件配置來恢復項目依賴包,同時就會生成新的project.json.lock文件。
project.json.lock
Project.json.lock 存儲編譯所需文件的列表(通常為 NuGet 引用)。與 project.json 文件不同,它包括特定的包版本號,可支持通配符。如果沒有 project.json.lock,將完整還原包。Project.json.lock 包括包圖片以及本地下載的其他與包相關的數據(已還原)。它的工作方式 和 npm以及 RubyGems非常相似,你可以把這個文件簽入版本庫,也可以不簽入,但此文件不存在時,將運行 NuGet restore 還原以重新創建。此文件列為 Visual Studio 中 project.json 的子項。
HellodotnetCore.xproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>34ee435f-9fda-4fb2-b4fb-a3203939f0c5</ProjectGuid>
<RootNamespace>HellodotnetCore</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
和以往的csproj 文件一樣,這個文件架起Visual Studio 和MSBuild溝通的橋梁。HellodotnetCore.xproj 定義構建項目時將發生的事項。最新版本可導入 Microsoft.DotNet.targets,它定義了利用新 DotNet.exe 命令的構建任務。與過去的 MSBuild proj 文件不同,xproj 文件非常小,因為大部分信息已(暫時)移到 project.json。不過后續這個文件要被csproj 替代,也許就在不久的將來的Visual Studio 2016上面就變成了csproj。
global.json
global.json是一個有待探究的神奇配置文件,我最喜歡的一個功能是全新的支持調試和單步執行,甚至可以實時修改包的源代碼。假設你有公司范圍的“框架”程序集,可以在眾多團隊之間共享。但是,
但是,框架包實際上是開源的,因此公司內(或者,甚至更好,公司外部)的任何人員均可進行完善和更改。現在,想像你如果為此框架引用 NuGet 包,但有時懷疑可能存在需要修復的缺陷或可能存在一個批準的增強功能。通常,這需要獨立于項目/解決方案處理組件中的源代碼。相反,如果你能夠下載源代碼并隨時開發將其更新為集成式體驗 - 甚至單步調試,而不依賴于符號服務器或 PDB 文件是否可用,會怎么樣? 幸運地是,Visual Studio 2015 支持此關鍵場景。
例如,想象你想要調試 GitHub 上可用的 Microsoft.Extensions.Logging 包。要在項目中對其進行添加和調試,你需要下載(可能使用 git clone 或 git submodule 命令)源代碼。接下來,為了使 Visual Studio 知曉在何處查找源代碼,你需要編輯 global.json 項目節點,如將“submodules\Logging”添加到查看的目錄列表:
{
"projects": [ "src", "test", "submodules\Logging" ],
"sdk": {
"version": "1.0.0-*"
}
}
當然,你可以提供完整路徑(例如,你未將代碼克隆到子目錄)。但是,請注意,目錄分隔符是兩個反斜杠 (\\) 或單個正斜線(如 c:/users/geffzhang/documents/visual studio2015/Projects/Microsoft.Extensions.Logging)。
更新并保存 global.json 后,一旦 Visual Studio 成功找到源代碼,它會自動將項目添加到你的解決方案,使你可以調試到源代碼。
這里使用了一種非常棒的算法來確定要加載的源代碼目錄:
- 如果 global.json 中指定的任何源代碼位置包含的文件夾具有與包相同的名稱(如 Microsoft.Extensions.Logging),且此文件夾包含名為 project.json 的文件,調試程序將使用此文件夾及其內部的源文件。
- 否則,會加載包文件夾中編譯的二進制程序。
本文簡要介紹了.NET Core項目中最為重要的一個配置文件project.json的內容和相關的工具,類庫等基礎信息,下篇文章我們來聊聊如何構建多個Project的解決方案的內容。
文章列表