如何打包面向 .NET Core 的可移植 .NET 庫?
如何以現代通用方式打包可移植的 .NET 庫?假設我有一個 AnyCPU 程序集,我希望將它提供給任何支持 .NET Core API 表面的 .NET 平台,例如 .NET Framework 4.6 和通用 Windows 平台。
這是一系列問題和答案,記錄了我對現代 NuGet 包創作主題的發現,特別關注 NuGet 3 引入的更改。您可能還對一些相關問題感興趣:
此答案基於用於打包面向 .NET Framework 的庫的原則。首先閱讀連結的答案以更好地理解以下內容。
要發布可移植 .NET 庫,您需要創建具有以下結構的 NuGet 包:
\---lib \---dotnet MyPortableLibrary.dll MyPortableLibrary.pdb MyPortableLibrary.XML所有三個文件都將來自發布建構配置下項目的建構輸出目錄。
上述結構中的
dotnet目錄具有特殊含義 - 它向 NuGet 指示該目錄中的文件將在您的包的所有依賴項都兼容的任何平台上使用。因此,您的包可自動在支持所有依賴項的任何 .NET 平台(例如 .NET Core)上使用。關鍵的下一步是確定依賴項列表。由於包管理問題,無法簡單地聲明對 .NET Core 本身的依賴(.NET Core 是所有 .NET 平台共享的 API 表面)。相反,您必須手動確定每個 .NET Core 組件依賴項並將其添加到 nuspec 文件中。
.NET Core 包的依賴檢測過程包括兩個步驟:
- 確定庫引用的 .NET Core 程序集。
- 確定包含這些程序集的 NuGet 包。
Visual Studio 不提供您需要的資訊。相反,您需要建構您的庫並檢查生成的 DLL 文件。以下 PowerShell 腳本將顯示 .NET 程序集的引用:
Get-ChildItem MyPortableLibrary.dll | % { [Reflection.Assembly]::LoadFile($_.FullName).GetReferencedAssemblies() | % { $_.Name + ".dll" } }此命令的輸出將是程序集名稱列表,例如:
System.Runtime.dll System.Resources.ResourceManager.dll System.Numerics.Vectors.dll獲得列表後,打開項目目錄中的 project.lock.json 文件。此文件包含有關項目使用的所有 NuGet 包的資訊。除了其他數據之外,您還會發現各種 JSON 塊,如下所示:
"System.Numerics.Vectors/4.1.0": { "dependencies": { "System.Globalization": "[4.0.10, )", "System.Resources.ResourceManager": "[4.0.0, )", "System.Runtime": "[4.0.20, )", "System.Runtime.Extensions": "[4.0.10, )" }, "frameworkAssemblies": [ "mscorlib", "System.Numerics" ], "compile": { "ref/net46/System.Numerics.Vectors.dll": {} }, "runtime": { "lib/net46/System.Numerics.Vectors.dll": {} } },此 JSON 塊表示“編譯”下列出的程序集文件由頂級值(System.Numerics.Vectors 版本 4.1.0)中列出的包提供。使用此資訊將每個引用的程序集映射到 NuGet 包。請注意,雖然包和程序集名稱通常相同,但情況並非總是如此!
對於不屬於 .NET Core 的任何 NuGet 包,您可以跳過上述過程,因為您已經知道您所依賴的確切包。此處描述的依賴檢測邏輯只是必需的,因為由於上面連結的問題,您無法直接在 .NET Core(Microsoft.NETCore 包)上聲明依賴。
現在只需根據以下範例列出 nuspec 文件中的所有依賴項:
<?xml version="1.0"?> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata minClientVersion="3.2"> <id>Example.MyPortableLibrary</id> <version>1.0.0</version> <authors>Firstname Lastname</authors> <description>Example of a portable library with NuGet package dependencies.</description> <dependencies> <dependency id="System.Numerics.Vectors" version="4.1.0" /> <dependency id="System.Resources.ResourceManager" version="4.0.0" /> <dependency id="System.Runtime" version="4.0.20" /> </dependencies> </metadata> <files> <file src="..\bin\Release\MyPortableLibrary.*" target="lib\dotnet" /> </files> </package>而已!生成的包可在任何兼容的 .NET 平台上使用,例如 .NET Framework 4.6 或通用 Windows 平台。請記住在創建 NuGet 包之前使用發布配置建構您的解決方案。
GitHub 上提供了範例庫和相關的打封包件。此答案對應的解決方案是 PortableLibrary。
請參閱Lucian Wischik 的部落格,以更深入地了解在此類 NuGet 包上執行的邏輯。