许多库面向特定版本的 .NET Framework。 例如,你可能有一个特定于 UWP 的库版本,另一个版本利用 .NET Framework 4.6 中的功能。 为了适应这一点,NuGet 支持将同一库的多个版本放在单个包中。
本文介绍 NuGet 包的布局,而不考虑如何生成包或程序集(也就是说,无论使用多个非 SDK 样式 .csproj 文件和自定义 .nuspec 文件还是单个多目标 SDK 样式 .csproj),布局都是相同的。 对于 SDK 样式的项目,NuGet 包目标 知道如何布局包,并自动将程序集放入正确的库文件夹中,并为每个目标框架(TFM)创建依赖项组。 有关详细说明,请参阅 支持在项目文件中使用多个.NET Framework版本。
使用创建包中所述的基于约定的工作目录方法时,必须按照本文中所述手动布局 包。 对于 SDK 样式的项目,建议使用自动化方法,但也可以选择按照本文中所述手动布局包。
框架版本文件夹结构
生成仅包含一个库版本或针对多个框架的包时,应始终使用以下约定:在 lib 下创建使用不同大小写的框架名称的子文件夹。
lib\{framework name}[{version}]
有关支持的名称的完整列表,请参阅 目标框架参考。
你不应该有一个不针对框架的库版本直接放在根 lib 文件夹中。 此功能仅限于 packages.config 支持。 这样做会使库与任何目标框架兼容,并允许它安装在任何地方,这可能导致意外的运行时错误。 使用 PackagesReference 格式时,已弃用在根文件夹(如 lib\abc.dll)或子文件夹(如 lib\abc\abc.dll)中添加程序集,并且这些操作会被忽略。
例如,以下文件夹结构支持特定于框架的程序集的四个版本:
\lib
\net46
\MyAssembly.dll
\net461
\MyAssembly.dll
\uap
\MyAssembly.dll
\netcore
\MyAssembly.dll
若要在生成包时轻松包含所有这些文件,请在以下**部分使用递归<files>通配符.nuspec:
<files>
<file src="lib\**" target="lib/{framework name}[{version}]" />
</files>
特定于体系结构的文件夹
如果您有特定于体系结构的程序集(即面向 ARM、x86 和 x64 的单独程序集),则必须将它们放在名为runtimes的文件夹中,并分别放置在子文件夹{platform}-{architecture}\lib\{framework}或{platform}-{architecture}\native中。 例如,以下文件夹结构能够同时容纳面向 Windows 10 和 uap10.0 框架的本机 DLL 和托管 DLL。
\runtimes
\win10-arm
\native
\lib\uap10.0
\win10-x86
\native
\lib\uap10.0
\win10-x64
\native
\lib\uap10.0
这些程序集仅在运行时可用,因此,如果您也想提供对应的编译时程序集,请在 /ref/{tfm} 文件夹中包含 AnyCPU 程序集。
请注意,NuGet 总是从一个文件夹中选取这些编译或运行时资产,因此,如果有一些来自/ref的兼容资产,那么来自/lib的用于添加编译时程序集的资产将被忽略。 同样,如果存在一些来自 /runtimes 的兼容资产,/lib 在运行时也会被忽略。
请参阅创建 UWP 包,以获得在.nuspec清单中引用这些文件的示例。
另请参阅 使用 NuGet 打包 Windows 应用商店应用组件
匹配项目中的程序集版本和目标框架
NuGet 安装具有多个程序集版本的包时,它会尝试将程序集的框架名称与项目的目标框架匹配。
如果未找到匹配项,NuGet 将复制低于或等于项目目标框架的最高版本的程序集(如果可用)。 如果未找到兼容的程序集,NuGet 将返回相应的错误消息。
例如,请考虑包中的以下文件夹结构:
\lib
\net45
\MyAssembly.dll
\net461
\MyAssembly.dll
在面向 .NET Framework 4.6 的项目中安装此包时,NuGet 会在文件夹中安装程序集 net45 ,因为该程序集是低于或等于 4.6 的最高可用版本。
如果项目面向 .NET Framework 4.6.1,NuGet 会在 net461 文件夹中安装程序集。
如果项目面向 .NET Framework 4.0 及更早版本,NuGet 会因找不到兼容的程序集而引发相应的错误消息。
按框架版本对程序集进行分组
NuGet 仅从包中的单个库文件夹中复制程序集。 例如,假设包具有以下文件夹结构:
\lib
\net40
\MyAssembly.dll (v1.0)
\MyAssembly.Core.dll (v1.0)
\net45
\MyAssembly.dll (v2.0)
当包安装在面向 .NET Framework 4.5 的项目中时, MyAssembly.dll (v2.0)是唯一安装的程序集。
MyAssembly.Core.dll (v1.0)未安装,因为它未在 net45 文件夹中列出。 NuGet 的这种行为是因为 MyAssembly.Core.dll 可能已合并到 MyAssembly.dll 的 2.0 版本中。
如果要 MyAssembly.Core.dll 为 .NET Framework 4.5 安装副本,请将 net45 副本放在文件夹中。
按框架配置文件描述对程序集进行分组
NuGet 还支持通过将短划线和配置文件名称追加到文件夹末尾来定位特定的框架配置文件。
lib{framework name}-{profile}
支持的配置文件如下所示:
-
client:客户端概要 -
full:完整档案 -
wp:Windows Phone -
cf:Compact Framework
声明依赖项 (高级)
打包项目文件时,NuGet 会尝试从项目自动生成依赖项。 本节中有关使用 .nuspec 文件声明依赖项的信息通常仅适用于高级方案。
(版本 2.0+)您可以在<group>文件的<dependencies>元素内为目标项目的目标框架声明包依赖项。 有关详细信息,请参阅 dependencies 元素。
每个组都有一个命名 targetFramework 的属性,其中包含零个或多个 <dependency> 元素。 当目标框架与项目的框架配置文件兼容时,这些依赖项一起安装。 有关确切框架标识符,请参阅 目标框架 。
建议对 lib/ 和 ref/ 文件夹中的文件使用每个目标框架名字对象(TFM)一个组。
以下示例显示了元素的不同变体 <group> :
<dependencies>
<group targetFramework="net472">
<dependency id="jQuery" version="1.10.2" />
<dependency id="WebActivatorEx" version="2.2.0" />
</group>
<group targetFramework="net20">
</group>
</dependencies>
确定要使用的 NuGet 目标
针对可移植类库进行库打包时,确定在文件夹名称和 .nuspec 文件中使用的 NuGet 目标可能会有些复杂,尤其是在仅针对 PCL 子集时。 以下外部资源将帮助你完成此作:
- .NET 中的框架配置文件 (stephencleary.com)
- 可移植类库配置文件 (plnkr.co):表枚举 PCL 配置文件及其等效的 NuGet 目标
- 可移植类库配置文件工具 (github.com):用于确定系统上可用的 PCL 配置文件的命令行工具
内容文件和 PowerShell 脚本
警告
packages.config 格式仅支持可变内容文件和脚本执行;它们在所有其他格式中已被弃用,不应在任何新包中使用。
借助packages.config,内容文件和 PowerShell 脚本可以使用文件夹内的contenttools相同文件夹约定按目标框架进行分组。 例如:
\content
\net46
\MyContent.txt
\net461
\MyContent461.txt
\uap
\MyUWPContent.html
\netcore
\tools
init.ps1
\net46
install.ps1
uninstall.ps1
\uap
install.ps1
uninstall.ps1
如果框架文件夹留空,NuGet 不会添加程序集引用或内容文件,也不会运行该框架的 PowerShell 脚本。
注释
由于 init.ps1 在解决方案级别执行,而不依赖于项目,因此它必须直接放置在文件夹下 tools 。 如果放置在框架文件夹下,则忽略它。