簡體   English   中英

nuget 包中 .netstandard2.0 和 .netframework47 DLL 的混合 - .netstandard 不可用

[英]Mix of .netstandard2.0 and .netframework47 DLLs in nuget package - .netstandard not available

首先,我不知道我所做的是否從根本上是錯誤的想法,所以答案可能是不這樣做,但這里是..

我有一個從 .nuspec 文件創建的包,在它的“文件”部分,它包含對 .net 標准和 .net 框架 DLL 的引用。 它還依賴於 .netstandard20 和 .netframework47。

這背后的原因是遺留庫是用框架編寫的,而新庫是用標准編寫的。

我們有一個使用 .netframework 4.7 編寫的消耗項目(實際上是幾個),需要處理兩組 DLL。 我已將項目更改為使用 PackageReference 而不是 packages.config,並且 Visual Studio 顯示正在引用部分中引用該包(而不是單個命名空間)。 當我構建時,.netframework DLL 被復制到 bin 文件夾中,而不是 .netstandard DLL。

我創建了一個臨時項目來隔離這個問題,我在那里也看到了同樣的情況。 該項目基本上只是拒絕承認標准的。 如果我將 using 語句添加到具有 .netstandard DLL 類型的類中,它只會在其下方放置一個紅色波浪線,並告訴我它在命名空間中不存在。

有人建議我將 .netstandard DLL 分解為它們自己的 NuGet 包,這是答案還是我遺漏了什么?

這里有一些例子..

.nu​​spec 文件:

<?xml version="1.0" encoding="utf-8"?>
<package >
  <metadata minClientVersion="2.5">
    <!-- other tags removed for brevity -->
    <dependencies>
      <group targetFramework=".NETStandard2.0"></group>
      <group targetFramework=".NETFramework4.7">
        <dependency id="NLog" version="3.1.0.0" />
      </group>
    </dependencies>
  </metadata>
  <files>
    <file src="..\Src\MyProj1\bin\Release\netstandard2.0\NetStandardClass.dll" target="lib\netstandard2.0" />
    <file src="..\Src\MyProj2\bin\Release\NetFrameworkClass1.dll" target="lib\net47" />
    <file src="..\Src\MyProj3\bin\Release\NetFrameworkClass2.dll" target="lib\net47" />
  </files>
</package>

包被稱為包,而不是其中的單個類型:

在此處輸入圖片說明

如果我嘗試手動添加引用 NetStandardClass 命名空間的 using 語句,則會將其標記為錯誤

在此處輸入圖片說明

包本身包含預期的所有 3 個 DLL:

在此處輸入圖片說明

然而,當我構建項目並檢查 bin 文件夾時,NetStandardClass DLL 不存在: 在此處輸入圖片說明

有人建議我將 .netstandard DLL 分解為它們自己的 NuGet 包,這是答案還是我遺漏了什么?

基本上,是的,拆分包裹就是答案。 另一種可能性是將 netstandard 程序集移動到 net47 文件夾中,或者將 net47 程序集移動到 netstandard2.0 文件夾中,但無論哪種方式都有可能出現問題。 雖然解決方案是重新編譯所有程序集,以便它們都使用相同的目標框架,但這也有其自身的問題。

如果您已閱讀 NuGet 文檔並得出結論,您正在嘗試的方法應該有效,請指出哪些文檔使您相信這一點,以便我可以更新文檔並嘗試消除混淆。

首先要了解 NuGet 為何支持具有多個目標框架文件夾的包,因為包可能希望在可能的情況下使用新的框架功能,但支持使用舊框架的包用戶。 因此,包作者需要其程序集的多個版本,具體取決於哪個版本與其用戶項目兼容。 因此,關鍵是 NuGet 需要根據項目使用的目標框架名稱 (TFM) 從包中選擇資產。 NuGet實際進行資產選擇的方式如下:

NuGet 查找包中存在哪些 TFM 文件夾,以獲取包支持的 TFM 列表。 通常它會查找lib/<tfm>/ref/<tfm>文件夾,但contentFiles/<tfm>build/<tfm>文件也可能相關。 請注意,它不會查看任何文件名。 哪些程序集存在於lib/net47/*.dlllib/netstanard2.0/*.dll下尚未考慮。

一旦有了這個包 TFM 列表,它就會查看項目 TFM,並選擇“最佳”TFM。 對於多目標的 SDK 樣式項目,它會為每個項目 TFM 執行一次。 “最佳”TFM 意味着相同的“系列”(net* 項目始終選擇 net* 資產,如果可用。僅當不存在 net* 程序集時,與 netstandard 兼容的 .NET Framework TFM 才會查找 netstandard* 資產)。

一旦為項目的 TFM 選擇了包 TFM,NuGet 就會選擇所有文件,如lib/<tfm>/*.dllref/<tfm>/*.dllcontentFiles/<tfm>/<lang>/*build/<tfm>/<package_id>.<props|targets>等等。

因此,您可以看到,如果您的包包含lib/net47/assembly1.dlllib/netstandard2.0/assembly2.dll ,NuGet 將只選擇這兩個程序集之一,而不會同時選擇這兩個程序集,具體取決於 net47 或 netstandard2.0更符合項目。

盡管如果 NuGet 對每個 TFM 進行 TFM 選擇,而不是先選擇 TFM,然后僅選擇該文件夾中存在的程序集,這似乎對您來說似乎是可取的,但請考慮何時包添加額外的輔助實用程序以“polyfill”具有以下功能的舊 TFM該軟件包用於較新的 TFM。 較新的 TFM 不需要此幫助器實用程序,因此 NuGet 不希望選擇它。

NuGet 團隊建議為每個程序集創建一個包,在這種情況下,這個問題永遠不會發生,因為 NuGet 會為每個包進行資產選擇,並且假設每個包都是正確創作的,一切都只是正確選擇。 如果您堅持將所有程序集捆綁在一個包中,根據我上面的描述,我希望您看到您需要將所有程序集放在一個 TFM 文件夾中,但是由於不同的程序集是針對不同的 TFM 編譯的,因此可能會出現問題,尤其是如果某些開發人員使用可能不支持 .NET Standard 的舊版 Visual Studio。 我強烈建議至少為每個 TFM 創建一個包,或者重新編譯所有程序集以使用相同的 TFM。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM