如何以现代通用方式打包可移植.NET库?让我们假设我有一个AnyCPU程序集,我希望它可用于任何支持.NET Core API表面的.NET平台,例如.NET Framework 4.6和通用Windows平台。
这是一系列问题和答案,记录了我对现代NuGet包创作主题的研究结果,特别关注NuGet 3引入的变化。您可能也对一些相关问题感兴趣:
- How to package a .NET Framework library?
- How to package a .NET library targeting the Universal Windows Platform?
- How to package a .NET library targeting .NET Framework and Universal Windows Platform and include platform-specific functionality?
- How to package a multi-architecture .NET library that targets the Universal Windows Platform?
- How to package a .NET library that targets the Universal Windows Platform and depends on Visual Studio extension SDKs?
答案 0 :(得分:12)
这个答案建立在principles used to package libraries targeting the .NET Framework之上。首先阅读链接的答案,以便更好地理解以下内容。
要发布可移植的.NET库,您需要创建一个具有以下结构的NuGet包:
\---lib
\---dotnet
MyPortableLibrary.dll
MyPortableLibrary.pdb
MyPortableLibrary.XML
所有这三个文件都来自Release build配置下项目的构建输出目录。
上述结构中的dotnet
目录具有特殊含义 - 它向NuGet指示目录中的文件将用于所有包依赖项兼容的任何平台上。因此,您的程序包可以自动在任何支持所有依赖项的.NET平台上使用(例如.NET Core)。
关键的下一步是确定依赖项列表。由于a package management issue,不可能简单地声明对.NET Core本身的依赖(.NET Core是所有.NET平台共享的API表面)。相反,您必须手动确定每个.NET Core组件依赖项并将其添加到nuspec文件中。
.NET Core包的依赖项检测过程包括两个步骤:
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块表示“compile”下列出的程序集文件由顶级值(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或Universal Windows Platform。在创建NuGet包之前,请记住使用Release配置构建解决方案。
示例库和相关的打包文件为available on GitHub。与此答案对应的解决方案是PortableLibrary。
请参阅Lucian Wischik's blog以深入了解在此类NuGet包上运行的逻辑。
答案 1 :(得分:-1)
在过去的几个月中,关于制作可移植.NET框架库/ NuGet包的最佳方法似乎有很多流失。如果你可以等一下,你会想要了解.NET Standard。 Immo Landwerth在2016年9月写了一篇详细的blog post introducing the .NET Standard。在.NET Core中支持.NET Standard 2.0是expected to arrive in early 2017,与Visual Studio 2017在同一时间段内,Release Candidate阶段。 .NET Standard 2.0将由.NET Framework,.NET Core和Xamarin实现。它还将包含.NET Framework二进制文件的兼容性填充程序,这应该使采用更容易。
<强>更新强>
Oren Novotny在这个主题上有一篇非常翔实的博客文章:Multi-targeting the world: a single project to rule them all。他讨论了.NET标准以及如何使用Visual Studio 2017进行多目标定位。博客文章来自Visual Studio 2017的RTM,但它非常有用。