NuGet是什么?理解与使用

如果你了解python,那么它类似pip。

如果你了解nodejs,那么它类似npm。

如果你了解ruby,那么它类似gem。

对,它就是一个包(package)管理平台,确切的说是 .net平台的包管理工具,它提供了一系列客户端用于生成,上传和使用包(package),以及一个用于存储所有包的中心库即NuGet Gallery,如果有需要也可以搭建自己的私有NuGet库。

NuGet 官方www.nuget.org

对于一个现代化的开发平台,建立一种让开发者创建,分享与使用可复用代码的机制是十分必要的。这种“可复用代码”被打包后的文件通常被称作“包”(package),对于.NET(包括 .NET Core)平台来说这个机制的实现就是NuGet平台。

NuGet的实现均为开源项目,包括了客户端工具,服务器,官方网站以及各语言的文档等。这些项目可以在下面的链接中找到。

NuGet on GitHubgithub.com

NuGet包的本质是一个以nupkg为后缀的zip压缩文件(你可以将后缀改为.zip后解压查看里面的内容),其中包含了编译后的Dll文件以及其他相关文件。下图显示nuget包从创建,上传到被使用的流程。

NuGet的客户端融合在各类开发工具中,包括但不限于:

  1. .net core SDK中的nuget命令行;

  2. Visual Studio中的nuget工具;

  3. nuget.exe 命令行客户端;

  4. Visual Studio Code中的nuget插件;

nuget客户端工具

在了解了nuget大致概念后我们可以通过发布一个nuget包来更仔细的了解如何使用nuget以及其中的重要概念。

下文会以开发中最常接触到的Visual Studio( 本文使用Visual Studio 2017 Community )做为演示工具来创建一个nuget包。要创建一个包首先需要一个 .net项目,可以看到项目的创建页面有很多选择,类库项目就可以选择三种(.net core的类库项目未显示在截图中) .Net Core;.Net Framework 还有 .Net Standard,到底应该选择哪一种呢?

Visual Studio 2017 项目创建窗口

为了做出选择,我们首先要深入理解TFMs和 .net standard这两个概念。首先创建一个 .net core类库项目。

.net core类库项目结构

在项目目录中打开csproj文件可以看见下面的内容。

<Project Sdk="Microsoft.NET.Sdk">  <PropertyGroup>    <TargetFramework>netcoreapp2.0</TargetFramework>  </PropertyGroup></Project>

可以看到该项目的TargetFramework为netcoreapp2.0,这里的netcoreapp2.0 就是TFMs,即Tagrget Framework Monikers 翻译过来就是“目标框架别名”,这个值指定了这个项目是跑在哪个Framework上的。

如今 .net平台有各种版本的Framework,在 .net core之前有 .Net Framework 1.0一直到现在的4.7等等各种版本, .net core现在有1.0/1.1/2.0/2.1。所有这些版本都有自己的代号/别名。全部的TFMs可以在下面的链接找到。

Target frameworksdocs.microsoft.com640?wx_fmt=jpeg

这仍然没有解决我们的问题:如何决定使用哪个Framework?现在需要引入 .Net Standard,它是一个标准, .net API的标准,用来描述每个Framework的API实现情况。标准的版本越往后支持的API就越多,也就兼容了之前的版本。

当前各个Framework的 .Net Standard版本如下图(如果你曾经了解Portable Class Libraries(PCL),它已经被 .net standard替代了,所以这里不多做说明。)

最新的内容可以在下面的链接中找到。

dotnet/standardgithub.com

所以要选择哪个Framework,首先要确定的是:1)你的项目要使用哪些API?2)你项目要兼容哪些Framework? 总的来说:

  1. 选择更高的版本,你将有更多的API可以使用。(更丰富的API)

  2. 选择更低的版本,有更多的项目可以使用你的库。(更好的兼容性)

所以 .net standard的选择原则就是:在API够用的情况下选择尽量低的 .net standard标准。这需要根据实际的项目需求来进行判断。

了解了TFMs和 .net standard后我们绕回来说NuGet,创建一个 .net standard 2.0 类库项目。

打开csproj我们可以看到

<Project Sdk="Microsoft.NET.Sdk">  <PropertyGroup>    <TargetFramework>netstandard2.0</TargetFramework>  </PropertyGroup></Project>

可以看到TargetFramework是netstandard2.0。如果我们需要更改TargetFraamework,可以选择项目【属性】在【应用程序】页面可以进行更改。

目标框架修改

为了演示我们为项目添加一个第三方包Newtonsoft.Json,右键点击项目选择管理NuGet程序包。

打开后可以在Visual Studio左侧看到下面的界面。

这里显示了项目已安装的包,这个包由我们选择的Target Framework隐式引用的。现在我们点击浏览,搜索Newtonsoft.Json。

120M的下载量,可见现在json的流行程度

点击安装。

安装完成后可以看到程序包管理器输出以下信息,并且引用中也添加了新的项目。

但是我并没有在项目文件夹下找到任何Newtonsoft.Json的程序集,包在哪?其实包被下载到了一个nuget公共目录,在我的Windows10系统上是 C:\Users\wangl\.nuget\packages,这样nuget包就不会被重复下载。而在项目中nuget仅仅将依赖信息写入了csproj项目文件与obj文件夹中的project.assets.json,其中csproj项目文件中的内容如下。

<Project Sdk="Microsoft.NET.Sdk">  <PropertyGroup>    <TargetFramework>netstandard2.0</TargetFramework>  </PropertyGroup>  <ItemGroup>    <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />  </ItemGroup></Project>

包所依赖的内容并不会被打包到最后的.nupkg文件中,NuGet只是将依赖信息写入包,在最终使用这些包的应用程序编译时还原所有的依赖。

至此我们简单了解了NuGet给项目添加引用的过程。对于更复杂情况的引用,如下图

项目引用示例

这个项目的依赖树中有三个对B包的引用,而三个包的版本要求可能是不相同的,但幸好我们只需要关心我们项目直接引用的包,因为Nuget会帮我们管理所有包的依赖并且对于被多次引用的包,Nuget会找出满足该包所有使用者的版本(不过因为版本要求冲突而找不到适合包的情况是有可能的)。如果需要更详细的了解nuget如何解析项目包的引用可以前往下面的链接。

NuGet Package Dependency Resolutiondocs.microsoft.com640?wx_fmt=jpeg

现在开始打包我们的类库项目,首先要为包设置一些诸如版本,作者等相关信息。右键点击项目选择【属性】,再选择【打包】页,可以在这里输入包的描述信息。

打开csproj项目文件,可以看到这些信息也是保存在其中的。

<Project Sdk="Microsoft.NET.Sdk">  <PropertyGroup>    <TargetFramework>netstandard2.0</TargetFramework>    <ApplicationIcon />    <OutputType>Library</OutputType>    <StartupObject />    <Authors>FishNo6</Authors>    <Company>FishNo6</Company>    <Product>DemoPackage</Product>    <Version>1.0.1</Version>    <AssemblyVersion>1.0.0.1</AssemblyVersion>    <FileVersion>1.0.0.1</FileVersion>    <Description>This package is a demonstration for Nuget package.</Description>  </PropertyGroup>  <ItemGroup>    <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />  </ItemGroup></Project>

填写好信息后保存。回到解决方案,右键点击项目选择【打包】,可以看到以下输出。

1>------ 已启动生成: 项目: FishNo6.DemoPackage, 配置: Debug Any CPU ------1>FishNo6.DemoPackage -> E:\labs\FishNo6.DemoPackage\FishNo6.DemoPackage\bin\Debug\netstandard2.0\FishNo6.DemoPackage.dll1>已成功创建包“E:\labs\FishNo6.DemoPackage\FishNo6.DemoPackage\bin\Debug\FishNo6.DemoPackage.1.0.1.nupkg”。========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

在对应目录就可以找到nupkg包文件了。如果你的电脑安装了NuGet Package Explorer可以直接双击打开包来查看信息,这个应用可以在Window Store中安装。

到此我们成功创建了一个NuGet包。

下篇内容包括如何将包上传到NuGet Gallary(NuGet官方库)以及更深入的了解NuGet平台。

最后附上NuGet官方文档。

NuGet Documentationdocs.microsoft.com640?wx_fmt=jpeg

那么开始,

一,如何解读NuGet Gallery上的包信息?

我们先以Newtonsoft.Json为例,在其NuGet页面上可以看到如下页面,其中包含了作者,描述,依赖等等信息。

640?wx_fmt=png


其中重要的依赖关系(部分)如下,

较大字体显示内容如.NETFramework 2.0表示Target Framework(目标框架),在Target Framework下面的为此Target Framework对应的依赖,所以用一句话可以解读为:“如果你项目的目标框架也是.NETFramework 2.0,那么你就不需要依赖任何其它包就可以使用这个包”。同样的下面.NETFramework 1.0的含义就是:“如果你的项目的目标框架为.NETFramework 1.0那么需要引用下面的包后才能使用该包。”不过这些都不需要你手动去引用,NuGet会在你安装该包时自动安装其依赖的包。

Newtonsoft.Json这样的包是NuGet平台上的典型,除此之外还有一些比较特殊但也非常重要的包。我们来看一下Microsoft.NETCore.Platforms,下面是这个包的页面。

可以看到这个包竟然没有任何依赖,这是因为这个包并不包含任何DLL,所以也不需要依赖任何目标框架,NuGet的包可以包含任何你想发布的文件而不仅仅是DLL程序集。

下面在介绍另一种比较特殊的包,元包(Meta Package), Microsoft.AspNetCore.All就是一个元包 ,下面是它的页面。

页面上显示和普通的包并没有区别,为了更直观的演示我们把这个包的nupkg文件下载到本地,解压后可以看到在其lib目录下面只包含了一个空文件。

其实这个包本身并不包含内容,它通过对其他包的依赖定义自己。元包是一个NuGet包的约定,描述了一组放在一起有意义的包(Metapackages are a NuGet package convention for describing a set of packages that are meaningful together.)

这样做的原因首先是因为NuGet的包管理是“细粒度”的,原则上每个程序集(DLL)都应该是一个包,这样可以带来以下几个好处:

  • 细粒度的包在开发、测试的过程中与其它包的关联有限。

  • 细粒度的包可以提供对不同操作系统和CPU的支持。

  • 细粒度的包可以只依赖某个特定的库。

  • 在发布应用时,未被引用的包不会成为应用的一部分,因此应用程序的体积会有更小。

但是对于某些情况,元包则有更多好处:

  • 在引用大量细粒度包时有更好的用户体验

  • 定义了一组经过测试且运行良好的包(包括指定的各种版本)

而下面这个元包比较特殊:Microsoft.NETCore.App,因为它不仅是元包也定义了框架,也就是我们项目里的目标框架(Tagrget Framework)。这会在解读这类目标框架的元包时造成一定的困惑,以 Microsoft.NETCore.App上的页面为例,因为他本身定义了目标框架。不过我们应该不会手动去引用这些包,这些包通常是在是设置目标框架是被项目隐式应用的。

下面这张图描述了这种关系:API定义了框架,框架用于元包中包的选择,而这些包给你提供了API的实现。

更多资料可以查看下面这篇文章和其中文译文,对你理解NuGet平台和包,元包,框架的设计很有帮助。

Packages, metapackages and frameworksdocs.microsoft.com640?wx_fmt=jpeg

二,如何上传NuGet包?

要上传NuGet包到NuGet Gallery,首先你需要一个NuGet账号或者微软账号,然后准备好你的nupkg文件就可以开始上传了。

下面简单介绍三种方式:

1,在NuGet Gallery网页上传包,这是最方便快捷的方式。登录NuGet Gallery 点击Upload菜单进入上传页面。

nuget gallery包上传页面

点击Browse选择你的包文件,页面将读取你的包信息并显示在页面上。

填写包的文档相关信息。

填写包的文档相关信息

确保所有信息正确后就可以点击Submit发布你的包了!

2,在NuGet Package Expolrer中上传包,这个应用可以在Windows Store中免费安装。在使用该工具上传包之前你需要一个API Key,因为除使用官方上传页面的方式外所有其他方式上传包都需要使用一个API Key,这个Key可以在官方网站获取。在个人帐号的下拉菜单中选择API Keys。

进入API Key管理页面,点击如下图的Create,开始创建一个API Key。

填写好Key的名称,过期时间,再选择该Key可以使用的功能和对应的包,点击确认成功创建后可以看到如下图的页面。

点击Copy就可以拷贝你的Key到剪贴板。有了API Key之后我们使用NuGet Explorer打开我们的包,在File菜单中选择Publish.

点击Publish后出现如下界面。

输入所需的API Key点击Publish。

3,使用 .net core SDK命令行上传包,可以执行dotnet nuget push的命令,其中第一个参数为包所在目录,若再当前目录可直接填入文件名, -k参数就是我们在上面所获取到的API Key,如下面的命令行示例。

dotnet nuget push foo.nupkg -k 4003d786-cc37-4004-bfdf-c4f3e8ef9b3a

该命令还有许多其他参数,更多信息可前往下面的链接:

dotnet nuget push command - .NET Core CLIdocs.microsoft.com640?wx_fmt=jpeg

需要注意的是包上传后是不能被删除的,只能被unlist。鉴于此我没有真的上传我的包,因为知道一个完全没有意义的包在我的账号里还无法删除会让我寝食难安的。大家可以自己动手尝试。

三,如何安装本地NuGet包?

以Visual Studio 2017 Community为例,打开你的项目,右键点击项目选择【管理NuGet程序包】。

然后点击NuGet程序包管理界面右上角的齿轮,出现下面的设置窗口。

点击+号新建一个可用程序包源,设置你想要的名称并选择源的所在目录,点击确定。

再次打开NuGet程序包器,你可以在程序包源选项中看到看添加的源,选中后就可以看到你在该本地路径中放置的包了!

四,NuGet包的内容与目录结构?

我们仍以Newtonsoft.Json包为例,将后缀改为.zip并解压后可以看到以下目录结构。

其中lib目录如下图,它保存了各个目标框架下对应的程序集。

Newtonsoft.Json.nuspec为xml格式的manifest文件保存了包的元数据,如作者,版本,包含内容等等信息。rels,[Content_Types].xml,package为打包时生成的文件。

除了这些目录外,包内还可以包含runtimes,content,build,tools等文件夹,下面介绍runtimes和content文件夹。

如果你的程序集对不同的操作系统有不同的实现,你需要将这些程序集按照下面的目录结构放入runtimes文件夹中。

\runtimes    \win10-arm        \native        \lib\uap10.0    \win10-x86        \native        \lib\uap10.0    \win10-x64        \native        \lib\uap10.0

而对于content文件夹,你可以把它看做是目标项目的根目录,也就是该文件夹下的内容会在包被安装时拷贝到项目的目录下。比如包里的content/images目录在包被安装之后就会在你的项目目录下放置一个images目录。

除了这些主要的文件夹,NuGet包里还可以包含build,tools等文件夹和文件,更多详细内容可查看下面的文档。

How to create a NuGet packagedocs.microsoft.com640?wx_fmt=jpeg

希望本篇能让你对.net的包管理平台有基本的了解,利用好NuGet平台会给你以后的项目开发提供很大的帮助。

原文地址:https://zhuanlan.zhihu.com/p/36767572


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315066.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P2468 [SDOI2010]粟粟的书架 主席树 + 二分 + 二维前缀和

传送门 文章目录题意&#xff1a;题意&#xff1a;题意&#xff1a; 给你一个n∗mn*mn∗m的矩阵&#xff0c;每次询问一个矩形&#xff0c;左上角是(x1,y1)(x_1,y_1)(x1​,y1​)&#xff0c;右上角是(x2,y2)(x_2,y_2)(x2​,y2​)&#xff0c;和一个hhh&#xff0c;问是否能选出…

带花树学习笔记

引入 带花树解决的是一般图的最大匹配问题。 学习此算法前你需要掌握二分图匹配的匈牙利算法&#xff0c;至少需要知道它的思想。 理论 众所周知&#xff0c;二分图匹配的思想是不断地找增广路。 严谨地讲&#xff0c;是找到了一条简单路径&#xff0c;它的起点和终点都未…

你竟然没用 Nuget 构建项目?

想写这篇文章缘起于公众号文章里的一条留言&#xff1a;对于一个现代化的开发平台&#xff0c;建立一种让开发者创建&#xff0c;分享与使用可复用代码的机制是十分必要的。这种“可复用代码”被打包后的文件通常被称作“包”&#xff08;package&#xff09;&#xff0c;对于.…

Codeforces Round #339 (Div. 1) D. Kingdom and its Cities 虚树 + dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; n≤1e5,∑k≤1e5,q≤1e5n\le1e5,\sum k\le1e5,q\le1e5n≤1e5,∑k≤1e5,q≤1e5。 思路&#xff1a; 经过分析&#xff0c;外敌占领的城市只有可能是两点的lcalcalca或者两点之间任意一点&#xff0c;是哪个点…

小白开学Asp.Net Core《四》 —— 使用AspectCore-Framework

小白开学Asp.Net Core《四》—— 使用AspectCore-Framework一、AspectCore-Framework说AspectCore-Framework不得不先谈谈的AOP&#xff0c;AOP&#xff1a;在软件业&#xff0c;AOP为Aspect Oriented Programming的缩写&#xff0c;意为&#xff1a;面向切面编程&#xff0c;通…

P4103 [HEOI2014]大工程 虚树 + dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 简化一下题意就是求树上给定点集中每两个点之间的距离之和&#xff0c;相距最远的点&#xff0c;相距最近的点。 对于距离和我们统计一下边的贡献就好啦&#xff0c;边两头的sizesizesize乘…

【翻译】Keras.NET简介 - 高级神经网络API in C#

用C#&#xff0c;远离996Keras.NETKeras.NET是一个高级神经网络API&#xff0c;它使用C#编写&#xff0c;并带有Python绑定&#xff0c;可以在Tensorflow、CNTK或Theano上运行。其关注点是实现快速实验。因为做好研究的关键是&#xff1a;能在尽可能短的时间内从一个想法发展出…

TIOBE 6月排行:C# 以微弱的优势超过了 Visual Basic .NET 的排名,再次进入 TOP 5

月经贴警告……TIOBE 编程语言排行榜 7 月更新已公布&#xff0c;排名前十的分别是&#xff1a;Java, C, Python, C, C#, Visual Basic .NET, JavaScript, PHP, SQL 和汇编语言。和上个月的不同之处主要是 C# 以微弱的优势超过了 Visual Basic .NET 的排名&#xff0c;再次进入…

用.NET Core实现一个类似于饿了吗的简易拆红包功能

需求说明以前很讨厌点外卖的我&#xff0c;最近中午经常点外卖&#xff0c;因为确实很方便&#xff0c;提前点好餐&#xff0c;算准时间&#xff0c;就可以在下班的时候吃上饭&#xff0c;然后省下的那些时间就可以在中午的时候多休息一下了。点餐结束后&#xff0c;会有一个好…

kubernetes实战篇之helm示例yaml文件文件详细介绍

前面完整示例里,我们主要讲解helm打包,部署,升级,回退等功能,关于这里面的文件只是简单介绍,这一节我们详细介绍一下这里面的文件,以方便我们参照创建自己的helm chart.Helm Chart 结构Chart 目录结构mychart/ Chart.yaml LICENSE README.md values.yaml requirements.yam…

P4309 [TJOI2013]最长上升子序列 平衡树 + dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 注意到一个很关键的条件&#xff0c;每次插入iii&#xff0c;而iii是递增的&#xff0c;也就是说插入iii之后只会从前面的最大值转移过来&#xff0c;所以我们现在只需要维护插入操作即可&…

【AGC035C】Skolem XOR Tree【异或】【构造】

传送门 题意&#xff1a;给定nnn&#xff0c;构造或判断无法构造一个2n2n2n个结点的树&#xff0c;其中结点iii和ininin的权值为iii,且所有iii和ininin路径权值异或和等于iii。 注意到 2i⊕2i112i\oplus2i112i⊕2i11&#xff0c;然后可以脑补出 然而111没处理 发现1⊕2⊕301\…

ASP.NET Core 管道再探

几乎任何服务器端处理环境都有自己的直通组件管道&#xff0c;用于检查、重路由或修改传入请求和传出响应。经典 ASP.NET 围绕 HTTP 模块理念进行排列&#xff0c;而 ASP.NET Core 采用基于中间件组件的更现代的体系结构。最终目的是相同的 - 允许可配置的外部模块以请求&#…

GRPC与.net core

QQ讨论群&#xff1a;953553560正文系列章节GRPC与.net coreGRPC截止时间与元数据GRPC与netcore IdentityGRPC与netcore IdentityServer4概述GRPC的数据交互模式有&#xff1a;1.单项RPC&#xff0c;最简单的数据交换方式&#xff0c;客户端发出单个请求&#xff0c;收到单个响…

程序员修神之路--做好分库分表其实很难之一

点击上方“蓝字”带你去看小星星菜哥&#xff0c;领导让我开发新系统了这么说领导对你还是挺信任的呀~必须的&#xff0c;为了设计好这个新系统&#xff0c;数据库设计我花了好多心思呢做一个系统我觉得不应该从数据库入手&#xff0c;应该从设计业务模型开始&#xff0c;先不说…

Office 365开发者的前端必备课程

这篇文章其实不仅仅是写给Office 365开发者的&#xff0c;但对于广大的Office 365开发者来说确实相当重要的。这里提到的Office 365开发者&#xff0c;包括了Office Add-ins&#xff0c;SharePoint Add-ins&#xff0c;Microsoft Graph&#xff0c;Microsoft Teams的开发者。我…

【CF1338C】Perfect Triples【位运算】【构造】

传送门 题意&#xff1a;有一序列SSS由下列方式生成&#xff1a; 找到字典序最小的正整数(a,b,c)(a,b,c)(a,b,c)&#xff0c;满足a,b,ca,b,ca,b,c不在SSS中且a⊕b⊕c0a\oplus b\oplus c0a⊕b⊕c0,其中⊕\oplus⊕为异或将a,b,ca,b,ca,b,c加入SSS重复第一步 TTT组数据&#xff…

.NET开发框架(五)-IIS上部署ASP.NET Core项目教程

在之前教程中&#xff0c;我们分享了框架的功能与视频演示介绍(文尾底部提供往期教程快捷链接)系列教程&#xff1a;从初学者到架构师的一步步蜕变本篇经验将和大家介绍如何在IIS上部署ASP.NET Core项目&#xff0c;希望对初学.NET CORE的童靴入门有所帮助&#xff01;1、打开V…

P4146 序列终结者 平衡树 + lazy维护

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 平衡树裸题&#xff0c;直接维护俩lazylazylazy就行了。 需要注意的是&#xff0c;只有儿子节点存在的时候才能更新&#xff0c;不然更新到000号节点之后&#xff0c;给000号点加上了奇怪的…

.NET开发框架(四)-服务器IIS实践教程

前三篇教程中&#xff0c;我们分享了框架的功能与视频演示介绍(文尾底部提供往期教程快捷链接)&#xff0c;今天开始我们进入实践教程&#xff0c;从0开始教学&#xff0c;让你从新手到架构师之兑变&#xff0c;目前已经重置了一台服务器&#xff0c;从安装与配置各组件开始学习…