NuGet 简介An introduction to NuGet

适用于任何现代开发平台的基本工具可充当一种机制,通过这种机制,开发人员可以创建、共享和使用有用的代码。An essential tool for any modern development platform is a mechanism through which developers can create, share, and consume useful code. 通常,此类代码捆绑到“包”中,其中包含编译的代码(如 DLL)以及在使用这些包的项目中所需的其他内容。Often such code is bundled into "packages" that contain compiled code (as DLLs) along with other content needed in the projects that consume these packages.

对于 .NET(包括 .NET Core),共享代码的 Microsoft 支持的机制则为 NuGet,其定义如何创建、托管和使用面向 .NET 的包,并针对每个角色提供适用工具。For .NET (including .NET Core), the Microsoft-supported mechanism for sharing code is NuGet, which defines how packages for .NET are created, hosted, and consumed, and provides the tools for each of those roles.

简单来说,NuGet 包是具有 .nupkg 扩展的单个 ZIP 文件,此扩展包含编译代码 (Dll)、与该代码相关的其他文件以及描述性清单(包含包版本号等信息)。Put simply, a NuGet package is a single ZIP file with the .nupkg extension that contains compiled code (DLLs), other files related to that code, and a descriptive manifest that includes information like the package's version number. 使用代码的开发人员共享创建包,并将其发布到公用或专用主机。Developers with code to share create packages and publish them to a public or private host. 包使用者从适合的主机获取这些包,将它们添加到项目,然后在其项目代码中调用包的功能。Package consumers obtain those packages from suitable hosts, add them to their projects, and then call a package's functionality in their project code. 随后,NuGet 自身负责处理所有中间详细信息。NuGet itself then handles all of the intermediate details.

由于 NuGet 支持公用 nuget.org 主机旁边的专用主机,因此,可以使用 NuGet 包来共享组织或工作组专用的代码。Because NuGet supports private hosts alongside the public nuget.org host, you can use NuGet packages to share code that's exclusive to an organization or a work group. 此外,你还可以使用 NuGet 包作为一种便捷的方式,将自己的代码用于除你自己项目之外的任何其他项目。You can also use NuGet packages as a convenient way to factor your own code for use in nothing but your own projects. 简而言之,NuGet 包是可共享的代码单元,但不需要暗示任何特定的共享方式。In short, a NuGet package is a shareable unit of code, but does not require nor imply any particular means of sharing.

包在创建者、主机和使用者之间的流The flow of packages between creators, hosts, and consumers

作为公用主机角色时,NuGet 自身负责在 nuget.org 中维护包含 100,000 多个唯一包的中央存储库。这些包每天供数以百万的 .NET/.Net Core 开发人员使用。In its role as a public host, NuGet itself maintains the central repository of over 100,000 unique packages at nuget.org. These packages are employed by millions of .NET/.NET Core developers every day. NuGet 还支持在云中(如在 Azure DevOps 上)、在私有网络中或者甚至直接在本地文件系统以私密方式托管包。NuGet also enables you to host packages privately in the cloud (such as on Azure DevOps), on a private network, or even on just your local file system. 通过这样做,这些程序包仅对那些有权访问主机的开发人员可用,使你能够将程序包提供给特定的一组用户。By doing so, those packages are available to only those developers that have access to the host, giving you the ability to make packages available to a specific group of consumers. 托管自己的 NuGet 源中提供了对相关选项的说明。The options are explained on Hosting your own NuGet feeds. 通过配置选项,你还可以精确控制任何给定计算机可以访问的主机,从而确保程序包是从特定源(而不是像 nuget.org 这样的公用存储库)获取的。Through configuration options, you can also control exactly which hosts can be accessed by any given computer, thereby ensuring that packages are obtained from specific sources rather than a public repository like nuget.org.

无论主机的本质是什么,它都可作为包创建者和包使用者之间的连接点。Whatever its nature, a host serves as the point of connection between package creators and package consumers. 创建者生成有用的 NuGet 包并将其发布到主机。Creators build useful NuGet packages and publish them to a host. 然后,使用者可以在可访问的主机上搜索有用且兼容的包,下载包并将其包含在项目中。Consumers then search for useful and compatible packages on accessible hosts, downloading and including those packages in their projects. 在项目中安装包后,包的 API 将可用于其余项目代码。Once installed in a project, the packages' APIs are available to the rest of the project code.

包创建者、包主机和包使用者之间的关系

包定向兼容性Package targeting compatibility

“兼容”包指:此包所包含的程序集应至少针对与使用项目的目标框架兼容的一个目标 .NET Framework 而生成。A "compatible" package means that it contains assemblies built for at least one target .NET framework that's compatible with the consuming project's target framework. 与 UWP 控件一样,开发人员可以创建特定于一个框架的程序包,也可以支持更广泛的目标。Developers can create packages that are specific to one framework, as with UWP controls, or they can support a wider range of targets. 为了最大限度地利用程序包的兼容性,开发人员的目标是所有 .NET 和 .NET Core 项目都可以使用的 .NET StandardTo maximize a package's compatibility, developers target .NET Standard, which all .NET and .NET Core projects can consume. 对于创建者和使用者而言,这是最有效的方式,因为单个包(通常包含单个程序集)适用于所有使用项目。This is the most efficient means for both creators and consumers, as a single package (usually containing a single assembly) works for all consuming projects.

另一方面,需要 .NET Standard 之外的 API 的程序包开发人员会为他们希望支持的不同目标框架创建单独的程序集,并将所有这些程序集包含在同一个程序包中(称为“多目标”)。Package developers who require APIs outside of .NET Standard, on the other hand, create separate assemblies for the different target frameworks they want to support and include all of those assemblies in the same package (which is called "multi-targeting"). 使用者安装此类包时,NuGet 将仅提取项目需要的程序集。When a consumer installs such a package, NuGet extracts only those assemblies that are needed by the project. 这能将包在该项目生成的最终应用程序和/或程序集中的占用量降到最低。This minimizes the package's footprint in the final application and/or assemblies produced by that project. 当然,多目标包对创建者来说更难维护。A multi-targeting package is, of course, more difficult for its creator to maintain.

备注

目标 .NET Standard 取代了以前使用各种可移植类库 (PCL) 目标的方法。Targeting .NET Standard supercedes the previous approach of using various portable class library (PCL) targets. 因此,此文档着重于为 .NET Standard 创建程序包。This documentation therefore focuses on creating packages for .NET Standard.

NuGet 工具NuGet tools

除托管支持外,NuGet 还提供各种供创建者和使用者使用的工具。In addition to hosting support, NuGet also provides a variety of tools used by both creators and consumers. 有关如何获取特定工具的信息,请参阅安装 NuGet 客户端工具See Installing NuGet client tools for how to obtain specific tools.

工具Tool 平台Platforms 适用方案Applicable Scenarios 描述Description
nuget.exe CLInuget.exe CLI 全部All 创建、使用Creation, Consumption 提供所有 NuGet 功能,包括一些专门适用于包创建者、仅适用于使用者和适用于两者的命令。Provides all NuGet capabilities, with some commands applying specifically to package creators, some applying only to consumers, and others applying to both. 例如,包创建者使用 nuget pack 命令通过各种程序集和相关文件创建包,包使用者使用 nuget install 在项目文件夹中包含包,而所有人都可使用 nuget config 设置 NuGet 配置变量。For example, package creators use the nuget pack command to create a package from various assemblies and related files, package consumers use nuget install to include packages in a project folder, and everyone uses nuget config to set NuGet configuration variables. 作为与平台无关的工具,NuGet CLI 不会与 Visual Studio 项目交互。As a platform-agnostic tool, the NuGet CLI does not interact with Visual Studio projects.
dotnet CLIdotnet CLI 全部All 创建、使用Creation, Consumption 直接在 .NET Core 工具链中提供特定 NuGet CLI 功能。Provides certain NuGet CLI capabilities directly within the .NET Core tool chain. 与 NuGet CLI 一样,dotnet CLI 不会与 Visual Studio 项目交互。As with the NuGet CLI, the dotnet CLI does not interact with Visual Studio projects.
包管理器控制台Package Manager Console Windows 版 Visual StudioVisual Studio on Windows 使用Consumption 提供用于在 Visual Studio 项目中安装和管理包的 PowerShell 命令Provides PowerShell commands for installing and managing packages in Visual Studio projects.
包管理器 UIPackage Manager UI Windows 版 Visual StudioVisual Studio on Windows 使用Consumption 提供用于在 Visual Studio 项目中安装和管理包的易用 UI。Provides an easy-to-use UI for installing and managing packages in Visual Studio projects.
管理 NuGet UIManage NuGet UI Visual Studio for MacVisual Studio for Mac 使用Consumption 提供用于在 Visual Studio for Mac 项目中安装和管理包的易用 UI。Provide an easy-to-use UI for installing and managing packages in Visual Studio for Mac projects.
MSBuildMSBuild WindowsWindows 创建、使用Creation, Consumption 支持创建包和还原项目中直接通过 MSBuild 工具链使用的包。Provides the ability to create packages and restore packages used in a project directly through the MSBuild tool chain.

如上文所述,你使用的 NuGet 工具很大程度上取决于用户要创建、使用还是发布程序包以及你所使用的平台。As you can see, the NuGet tools you work with depend greatly on whether you're creating, consuming, or publishing packages, and the platform on which you're working. 包创建者通常也是使用者,因为他们以其他 NuGet 包中已存在的功能作为生成基础。Package creators are typically also consumers, as they build on top of functionality that exists in other NuGet packages. 当然,这些包反过来可能也需要依赖其他包。And those packages, of course, may in turn depend on still others.

有关详细信息,请从包创建工作流包使用工作流文章开始。For more information, start with the Package creation workflow and Package consumption workflow articles.

管理依赖项Managing dependencies

在其他人的工作基础上轻松生成,这是使程序包管理系统成为最强大功能的方法之一。The ability to easily build on the work of others is one of most powerful features of a package management system. 相应地,大部分 NuGet 的用途就是代表项目管理该依赖关系树或“关系图”。Accordingly, much of what NuGet does is managing that dependency tree or "graph" on behalf of a project. 简单来说,你仅需要关注在项目中直接使用的包。Simply said, you need only concern yourself with those packages that you're directly using in a project. 如果任何这些包本身使用其他包(这些包仍可以使用其他包),NuGet 将负责所有这些下层依赖项。If any of those packages themselves consume other packages (which can, in turn, consume still others), NuGet takes care of all those down-level dependencies.

下图显示一个依赖于五个包的项目,这些包反过来也依赖于许多其他包。The following image shows a project that depends on five packages, which in turn depend on a number of others.

.NET 项目的 NuGet 依赖项关系图示例

请注意,某些包在依赖项关系图中多次出现。Notice that some packages appear multiple times in the dependency graph. 例如,包 B 有三个不同的使用者,并且每个使用者可能为该包指定不同版本(未显示)。For example, there are three different consumers of package B, and each consumer might also specify a different version for that package (not shown). 这是一种常见情况,特别是对于广泛使用的程序包。This is a common occurrence, especially for widely-used packages. 幸运的是,NuGet 将执行所有困难的工作来确定包 B 的哪一个版本可满足所有使用者。NuGet fortunately does all the hard work to determine exactly which version of package B satisfies all consumers. 随后,无论依赖项关系图多么复杂,NuGet 都将对所有包执行相同操作。NuGet then does the same for all other packages, no matter how deep the dependency graph.

有关 NuGet 如何实现此服务的更多详细信息,请参阅依赖项解析For more details on how NuGet performs this service, see Dependency resolution.

跟踪引用和还原包Tracking references and restoring packages

项目可在开发人员计算机、源代码管理存储库、生成服务器等位置之间轻松移动,因此将 NuGet 包的二进制程序集直接绑定到项目非常不切实际。Because projects can easily move between developer computers, source control repositories, build servers, and so forth, it's highly impractical to keep the binary assemblies of NuGet packages directly bound to a project. 这样做不仅会使项目的每个副本出现不必要的膨胀(而且会浪费源代码管理存储库中的空间)。Doing so would make each copy of the project unnecessarily bloated (and thereby waste space in source control repositories). 还会使包二进制文件难以更新到新版本(因为这需要更新项目的所有副本)。It would also make it very difficult to update package binaries to newer versions as updates would have to be applied across all copies of the project.

而 NuGet 维护一个项目所依赖的包的简单引用列表,包括顶层和下层的依赖关系。NuGet instead maintains a simple reference list of the packages upon which a project depends, including both top-level and down-level dependencies. 也就是说,每当你将某个主机中的包安装到项目中时,NuGet 都将在此引用列表中记录包标识符和版本号。That is, whenever you install a package from some host into a project, NuGet records the package identifier and version number in the reference list. (当然,卸载包将从列表中删除此信息。)然后,NuGet 根据请求提供还原所有引用程序包的方法,如软件包还原中所述。(Uninstalling a package, of course, removes it from the list.) NuGet then provides a means to restore all referenced packages upon request, as described on Package restore.

NuGet 引用列表在包安装时创建,可用于在其他位置还原包

只需引用列表,NuGet 随后即可随时从公共和/或私有主机重新安装—即“还原”—所有这些包。With only the reference list, NuGet can then reinstall—that is, restore—all of those packages from public and/or private hosts at any later time. 将项目提交到源代码管理存储库或将其以其他方式进行共享时,只需包含引用列表,不需要包含任何包二进制文件(请参阅包和源代码管理)。When committing a project to source control, or sharing it in some other way, you include only the reference list and exclude any package binaries (see Packages and source control.)

接收项目的计算机(如获得项目副本并将其作为自动部署系统的一部分的生成服务器)仅会在需要时要求 NuGet 还原依赖项。The computer that receives a project, such as a build server obtaining a copy of the project as part of an automated deployment system, simply asks NuGet to restore dependencies whenever they're needed. Azure DevOps 等生成系统会出于此确切目的提供“NuGet 还原”步骤。Build systems like Azure DevOps provide "NuGet restore" steps for this exact purpose. 同样,当开发人员获取项目副本(如克隆存储库时),他们可以调用 nuget restore(NuGet CLI)、dotnet restore(dotnet CLI) 或 Install-Package(程序包管理器控制台)类似的命令,以获得所有必要的程序包。Similarly, when developers obtain a copy of a project (as when cloning a repository), they can invoke command like nuget restore (NuGet CLI), dotnet restore (dotnet CLI), or Install-Package (Package Manager Console) to obtain all the necessary packages. 对于 Visual Studio 来说,它将在生成项目时自动还原包(前提是启用了自动还原,如包还原中所述)。Visual Studio, for its part, automatically restores packages when building a project (provided that automatic restore is enabled, as described on Package restore).

显然,开发人员接下来关注的 NuGet 的主要角色则是代表项目维护该引用列表并提供高效还原(和更新)这些引用包的方法。Clearly, then, NuGet's primary role where developers are concerned is maintaining that reference list on behalf of your project and providing the means to efficiently restore (and update) those referenced packages. 该列表以两种“包管理格式”中的一种维护,因为将它们称为:This list is maintained in one of two package management formats, as they're called:

  • packages.config:(NuGet 1.0+) 一种 XML 文件,用于维护项目中所有依赖项的简单列表,包括其他已安装包的依赖项。packages.config: (NuGet 1.0+) An XML file that maintains a flat list of all dependencies in the project, including the dependencies of other installed packages. 已安装或已还原的包存储在 packages 文件夹中。Installed or restored packages are stored in a packages folder.

  • PackageReference(或“项目文件中的包引用”) | (NuGet 4.0+) 维护直接位于项目文件中的项目顶层依赖项的列表,因此无需单独文件。PackageReference (or "package references in project files") | (NuGet 4.0+) Maintains a list of a project's top-level dependencies directly within the project file, so no separate file is needed. 关联文件 obj/project.assets.json 动态生成,以管理项目使用的包的总依赖项关系图以及所有下层依赖项。An associated file, obj/project.assets.json, is dynamically generated to manage the overall dependency graph of the packages that a project uses along with all down-level dependencies. PackageReference 始终由 .NET Core 项目使用。PackageReference is always used by .NET Core projects.

任何特定项目中所用的包管理格式取决于项目类型以及 NuGet(和/或 Visual Studio)的可用版本。Which package management format is employed in any given project depends on the project type, and the available version of NuGet (and/or Visual Studio). 若要确认当前使用的格式,只需在安装第一个包后在项目根目录中查找 packages.configTo check what format is being used, simply look for packages.config in the project root after installing your first package. 如果没有该文件,请直接在项目文件中查找 <PackageReference> 元素。If you don't have that file, look in the project file directly for a <PackageReference> element.

当进行选择时,我们建议使用 PackageReference。When you have a choice, we recommend using PackageReference. 出于与旧版兼容目的对 packages.config 进行维护,将不再主动对其进行开发。packages.config is maintained for legacy purposes and is no longer under active development.

提示

各种 nuget.exe CLI 命令(如 nuget install)不会自动将包添加到引用列表中。Various nuget.exe CLI commands, like nuget install, do not automatically add the package to the reference list. 当使用 Visual Studio 包管理器(UI 或控制台)并使用 dotnet.exe CLI 时,将更新此列表。The list is updated when installing a package with the Visual Studio Package Manager (UI or Console), and with dotnet.exe CLI.

NuGet 的其他功能What else does NuGet do?

到目前为止,你已经学习了 NuGet 的以下特征:So far you've learned the following characteristics of NuGet:

  • NuGet 提供支持专用托管的中心 nuget.org 存储库。NuGet provides the central nuget.org repository with support for private hosting.
  • NuGet 为开发人员提供创建、发布和使用包所需的工具。NuGet provides the tools developers need for creating, publishing, and consuming packages.
  • 最重要的是,NuGet 能维护项目中所用包的引用列表,并且能够通过该列表还原和更新这些包。Most importantly, NuGet maintains a reference list of packages used in a project and the ability to restore and update those packages from that list.

为使这些进程高效运行,NuGet 执行了一些后台优化。To make these processes work efficiently, NuGet does some behind-the-scenes optimizations. 最值得注意的是,NuGet 管理包缓存和全局包文件夹,使安装和重新安装过程更为快捷。Most notably, NuGet manages a package cache and a global packages folder to shortcut installation and reinstallation. 缓存可避免下载已在计算机上安装的包。The cache avoids downloading a package that's already been installed on the machine. 全局包文件夹允许多个项目共享同一个已安装的包,因此减少了计算机上的 NuGet 的总体占用。The global packages folder allows multiple projects to share the same installed package, thereby reducing NuGet's overall footprint on the computer. 当在生成服务器等位置频繁还原大量包时,缓存和全局包文件夹也非常有帮助。The cache and global packages folder are also very helpful when you're frequently restoring a larger number of packages, as on a build server. 有关这些机制的详细信息,请参阅管理全局包和缓存文件夹For more details on these mechanisms, see Managing the global packages and cache folders.

在一个单独的项目中,NuGet 管理整个依赖项关系图,它同样包括解析对同一个包的不同版本的多个引用。Within an individual project, NuGet manages the overall dependency graph, which again includes resolving multiple references to different versions of the same package. 项目在具有相同依赖项的一个或多个包上选取依赖项是很常见的情况。It's quite common that a project takes a dependency on one or more packages that themselves have the same dependencies. nuget.org 上的某些最有用的实用程序包即由其他许多包使用。Some of the most useful utility packages on nuget.org are employed by many other packages. 然后在整个依赖项关系图中,你可以对同一个包的不同版本轻松发起 10 种不同的引用。In the entire dependency graph, then, you could easily have ten different references to different versions of the same package. 为避免将该包的多个版本引入应用程序本身,NuGet 会挑选出一个适合所有使用者的版本。To avoid bringing multiple versions of that package into the application itself, NuGet sorts out which single version can be used by all consumers. (有关详细信息,请参阅依赖项解析。)(For more information, see Dependency Resolution.)

除此之外,NuGet 维护与如何构造包(包括本地化调试符号)和如何引用包(包括版本范围预发行版本)相关的所有规范。此外,NuGet 还提供了各种 API 以编程方式使用其服务,并可为编写 Visual Studio 扩展和项目模板的开发人员提供支持。Beyond that, NuGet maintains all the specifications related to how packages are structured (including localization and debug symbols) and how they are referenced (including version ranges and pre-release versions.) NuGet also provides various APIs to work with its services programmatically, and provides support for developers who write Visual Studio extensions and project templates.

请花一点时间浏览本文档的目录,你会看到其中列出了所有这些功能,以及自 NuGet 首次发行起的发行说明。Take a moment to browse the table of contents for this documentation, and you see all of these capabilities represented there, along with release notes dating back to NuGet's beginnings.

评论、建议和问题Comments, contributions, and issues

最后,我们非常欢迎针对此文档给出评论和建议 — 只需在任何页面上选择“反馈”和“编辑”命令,或访问 GitHub 上的文档存储库文档问题列表Finally, we very much welcome comments and contributions to this documentation—just select the Feedback and Edit commands on the top of any page, or visit the docs repository and docs issue list on GitHub.

我们同样欢迎通过多种 GitHub 存储库针对 NuGet 本身提出建议;有关 NuGet 的问题,请访问 https://github.com/NuGet/home/issuesWe also welcome contributions to NuGet itself through its various GitHub repositories; NuGet issues can be found on https://github.com/NuGet/home/issues.

请尽情享受 NuGet 体验!Enjoy your NuGet experience!