2017-11-18 275 views
6

我一直在使用a .NET Standard project和NuGet。我有一個工作項目,並有uploaded it to NuGet.org。我的項目面向.NET Standard 1.3,其中包括.NET Framework 4.6和.NET Core 1.0。爲什麼我的.NET Standard NuGet包會觸發如此多的依賴關係?

但是,當我試圖將我的項目(通過NuGet)添加到新的.NET Framework 4.6項目時,依賴關係解析爲包!它們都是系統庫,似乎是Microsoft.NETCore.Platforms或NETStandard.Library 1.6.1的依賴項。 (Gist of full PM output.

我的項目只進口(using)一些庫,我沒有手動添加;即它們都是「附帶」.NET標準的庫。這些庫是:

  1. 系統
  2. System.Text
  3. 的System.Reflection
  4. System.Linq的
  5. System.Collections.Generic;

的事情是,我決定把我的項目目標.NET標準,因爲我想它跨越.NET Framework和.NET核心應用無縫協作。我認爲標準的全部內容是設定兼容性的最低水平。通過擴展,我想我假定(也許是錯誤的)像System.Console這樣的庫可以在Core或Framework中自動獲得。

當我在同一解決方案中將我的標準項目作爲Framework和Core項目中的依賴項進行測試時,我沒有注意到任何此類事情,所以我很懷疑這可能是NuGet的事情。

這裏究竟發生了什麼?我怎樣才能讓我的.NET標準庫在NuGet上可用,而不需要大量的依賴關係?

這是我指定我的NuGet包的方式問題嗎?或者我從根本上誤解了什麼?

+0

您是否注意到是否有任何內容實際添加到輸出文件夾中,或者在安裝軟件包時它是否只是一個可怕的依賴列表?我的經驗是它是後者,這仍然不是很好,但不是令人擔憂。 –

+0

@JonSkeet我的軟件包文件夾裏現在有一長串文件夾,當時我真的只想到一個文件夾。另外,「管理NuGet包」屏幕顯示所有包(其中一些包含未決更新)。 –

+2

正確 - 但bin目錄中有什麼? (FWIW,我完全同意這是一個非常不幸的情況。我不知道它是否在以後的版本中有所改進。但這就是爲什麼對於我生產的一些軟件包,我創建了net45目標以及netstandard1.x版本......) –

回答

9

你沒有做錯任何事,預計會發生。如果您只想將自己的DLL添加到新的.NET Framework項目中,則必須將.NET Standard 2.0作爲您的庫的等待.NET Framework版本,該版本本身支持API和程序集版本 - 這會進行爲4.7.2(雖然.NET Framework 4.7.1支持所有的API,但是有些程序集是如何版本化的,所以工具(VS 2017 15.5+)會添加額外的程序集來解決這個問題)。

您所看到的是.NET Standard如何構建以及對支持的框架的支持是如何實現的副作用。基於您的目標.NET標準版本和用於引用庫軟件包的工具,這也是不同的。

在.NET標準< 2.0中,您引用了NETStandard.Library元程序包,該元程序包又引用了其他(System.*)程序包。這些軟件包包含構成「.NET標準合同」的引用程序集 - 一組API和程序集名稱+版本。

當您爲.NET Standard 1.0-1.6創建的NuGet包被應用程序引用時,這些單獨的包不會引入引用程序集,而是引入應用程序所針對的框架的實現程序集。

對於.NET Core,這些匹配已經是運行時的一部分的程序集,因此DLL文件不會在構建的應用程序旁邊結束。然而,當.NET Core 1.1發佈了一套新的軟件包(NETStandard.Library版本1.6.1)時,這一點發生了變化。這導致爲.NET Core 1.0構建的應用程序最終得到了更新的實現程序集,這些程序集旨在包含在.NET Core 1.1中(幸運的是,1.1因此而成爲「長期支持」版本,因爲這引發了關於哪些程序集是LTS承諾的一部分)。

在.NET Framework上,這些庫(有一些例外如System.Net.Http)做的不多 - 它們只是轉發給系統組件。因此,例如「合同」定義System.ObjectSystem.Runtime.dll組件中定義。因此,最終在.NET Framework應用程序中使用的System.Runtime.dll文件包含System.Runtime.dll,其中包含向.NET Framework的mscorlib.dll轉發的類型。 .NET Core已經包含了一個不同的System.Runtime.dll,它爲該平臺做了一些不同的事情。這種機制允許單個DLL文件在兩個平臺上工作,因爲這些類型的轉發和附加實現確保在兩個實現上工作的「契約」(類型+程序集+程序集版本)相同。

.NET標準2.0旨在減少必要的程序包和DLL的數量,並在每次發佈新的.NET Core版本時刪除需要更新至NETStandard.Library

因此,對於.NET Standard 2.0和.NET Core 2.0,NETStandard.Library軟件包僅提供用於將代碼編譯到項目的引用程序集,但生成的NuGet程序包不再依賴於此程序包。因此,當您創建一個以.NET Standard 2.0爲目標的庫併發布它時,它將不具有NuGet依賴關係(除非添加其他內容)。

消費.NET標準庫時引入什麼「支持庫」的邏輯已移至構建期間使用的工具。因此,當包含對netstandard.dll的引用的庫被添加到.NET Framework項目時,工具將根據所使用的.NET Framework版本添加必要的支持DLL。這是針對.NET標準2.0以及.NET標準1.5+完成的,因爲.NET Framework 4.6.1通過這些類型的DLL文件追溯地與.NET標準2.0(以前是1.4)兼容。同樣的工具也確保即使NuGet包以某種方式被引入到這樣的應用程序項目中,通過NuGet引入的任何.NET標準實現庫都將從構建中移除。因此,如果您參考.NET Core 1.0發佈時構建的.NET Standard 1.0 NuGet包,則它的所有NuGet依賴關係都將被修剪掉,您將獲得構建工具附帶的支持庫。

這個想法是,.NET Framework 4.7.1將包含所有必要的程序集「收件箱」,以便netstandard.dllSystem.Runtime.dll等等是.NET Framework的一部分,任何.NET Standard 1.0-2.0 DLL文件都將「只是工作「,問題在於這些」收件箱「dll文件的版本號對於某些程序集來說太低,所以程序庫將無法加載 - 通過再次更改工具以包含具有更高版本號的DLL文件作爲支持庫轉向「收件箱」.NET Framework程序集。這計劃在.NET Framework 4.7.2中修復。

+0

謝謝馬丁。花了我一段時間來充分消化這個非常全面的答案。我想.NET標準仍然處於初級階段,這是最大的難題之一。我會坐下來等待Framework的4.7.2版本。 –

+0

我的注意力已被吸引到一種解決方法:http://blog.tdwright.co.uk/2017/11/21/update-getting-net-standard-apps-playing-nicely-on-nuget/ –

+1

是的,NuGet的在考慮別人之前,get-nearest-framework邏輯更傾向於使用較低版本的相同目標框架(所以'net471'項目甚至會選擇'net35' over'netstandard2.0') –

相關問題