歡迎光臨
每天分享高質量文章

自動將 NuGet 包的取用方式從 packages.config 升級為 PackageReference

在前段時間我寫了一篇遷移 csproj 格式的部落格 將 WPF、UWP 以及其他各種型別的舊 csproj 遷移成基於 Microsoft.NET.Sdk 的新 csproj,不過全過程是手工進行的,而且到最後處理 XAML 問題也非常頭疼。

現在,我們可以利用工具自動地完成這個過程。當然,工具並不將 csproj 格式進行遷移,而是在不遷移格式的情況下,使用到 PackageReference 方式 NuGet 取用帶來的好處。


本文內容
  • 自動升級

  • 檢查升級後的相容性問題

    • install.ps1 指令碼將失效

    • 使用 content 方式指定的內容資產將失效

    • XDT 變換將失效

    • lib 根目錄中的程式集將被忽略

  • 解決升級後的編譯錯誤

    • 參考資料

自動升級

下載安裝 Visual Studio 外掛 NuGet PackageReference Upgrader。在安裝完成之後,再次啟動 Visual Studio,則可以開始遷移。

更新:自 Visual Studio 2017 的 15.7 版本開始,遷移工具已經自帶到 Visual Studio 中。詳情請參見:Migrating from package.config to PackageReference formats – Microsoft Docs。

只有一個步驟:在 packages.config 檔案上點選右鍵,選擇 Upgrade to PackageReference

在彈出的介面中,選擇包的版本,確定即可完成一個專案的遷移。

相比於之前寫的手工遷移,自動遷移方式沒有改變 csproj 的格式,而只是將 NuGet 的取用方式改成了 PackageReference。具體有哪些好處,可以閱讀 將 WPF、UWP 以及其他各種型別的舊 csproj 遷移成基於 Microsoft.NET.Sdk 的新 csproj。

檢查升級後的相容性問題

packages.config 的 NuGet 包的管理方式有些功能是 PackageReference 沒有的。當然,沒有這些功能是因為“不需要”,而不是“還沒支援”;所以大部分的遷移都不會發生問題(除非釋出包使用的是特別老舊的 nuget.exe,或者釋出者利用了一些喪心病狂的黑科技)。

在 Visual Studio 2017 的 15.7 版本以上自帶的遷移工具中,會自動列出可能的相容性問題。

install.ps1 指令碼將失效

使用 PackageReference 後,在安裝和寫在的過程中 install.ps1 指令碼將不再執行。如果有一些行為依賴於此指令碼,那麼這個 NuGet 包的行為可能不正常。

但是,不用擔心!install.ps1 的存在是因為 packages.config 不支援 PackageReference 中的一些新特性(例如 NuGet 包中新的目錄結構,例如包中自帶的 msbuild targets)。所以,如果 NuGet 包在釋出時滿足目錄要求,那麼即便 install.ps1 不用執行也能保證包的行為正常。

使用 content 方式指定的內容資產將失效

PackageReference 使用 contentFiles 來管理內容資產,這樣可以更好地在多個依賴包之間傳遞和共享。而此前 content 指定的資產將失效。

建議檢查所有依賴的 NuGet 包,如果你有許可權修改部分依賴包,那麼請使用 contentFiles 來替代 content

XDT 變換將失效

使用 PackageReference 後,在安裝和寫在的過程中 XDT 轉換將不會執行,並且會忽略 .xdt 檔案。

在 Web 應用開發中會更留意這個問題。

lib 根目錄中的程式集將被忽略

lib 檔案夾內的程式集都應該按照標的框架建立子檔案夾,例如 net45、netstandard2.0、netcoreapp2.0。PackageReference 要求只能取用在某個標的框架下的程式集。

如果是使用預設的方式建立的 NuGet 包,基本上不會遇到這樣的問題。除非你在建立 NuGet 包時有自定義操作在根目錄放了程式集。

解決升級後的編譯錯誤

最可能出現的編譯問題是 NuGet 包取用的版本衝突。

packages.config 方式的包取用要求在 csproj 檔案中顯式指定一個依賴的包的版本,於是無論依賴使用了哪個版本,最終都由顯式指定的版本來指定。

而 PackageReference 的取用方式是自動管理依賴版本的,只要每個包都在允許的版本範圍之內,就自動選擇版本,並顯示在解決方案的取用中。

PackageReference 出現依賴衝突的提示通常是這樣的:

Version conflict detected for NuGet.Versioning. Reference the package directly from the project to resolve this issue.
NuGet.Packaging 3.5.0 -> NuGet.Versioning (= 3.5.0)
NuGet.Configuration 4.0.0 -> NuGet.Versioning (= 4.0.0)

也就是說,取用的兩個不同的包要求依賴相同包的不同版本,於是 PackageReference 無法隱式推斷依賴包的版本。這時需要將專案的依賴方式改為之前的方式。

當然,在製作和釋出 NuGet 包時,儘量使用非特定版本的依賴包,能夠極大地避免這種問題帶來的影響。關於如何指定非特定版本的依賴包,可以閱讀 Version ranges and wildcards 版本範圍和萬用字元。


參考資料

  • Migrating from package.config to PackageReference formats – Microsoft Docs

  • packages.config (PC) to PackageReference (PR) Migrator · NuGet/Home Wiki


原文地址:https://walterlv.com/post/migrate-packages-config-to-package-reference.html


.NET社群新聞,深度好文,歡迎訪問公眾號文章彙總 http://www.csharpkit.com