如果你了解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.com

这仍然没有解决我们的问题:如何决定使用哪个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.com

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

打开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.com

那么开始,

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

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

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

较大字体显示内容如.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.com

二,如何上传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.com

需要注意的是包上传后是不能被删除的,只能被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.com

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

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


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

NuGet是什么?理解与使用相关推荐

  1. NuGet 是什么? 理解与使用

    NuGet 是什么? 理解与使用 NuGet 是一个自由开源软件包管理系统,用于Microsoft开发平台,以前称NuPack. NuGet 作为 Visual Studio 扩展,能够简化在 Vis ...

  2. 关于 项目中Ioc基础模块 的搭建 (已适用于.net core / .net Framework / Nancy)

    Ioc (Inversion of Control, 控制反转)把创建对象的操作交给框架,亦被称为 DI(Dependency Injection, 依赖注入). 为什么叫做 "控制反转&q ...

  3. NuGet是什么?理解与使用(下)

    本篇将回答下面几个问题: 如何解读NuGet Gallery上的包信息? 如何上传NuGet包到NuGet Gallery? 如何安装本地NuGet包? NuGet包的内容文件与目录结构? 如果你没看 ...

  4. NuGet是什么?理解与使用(上)

    如果你了解python,那么它类似pip. 如果你了解nodejs,那么它类似npm. 如果你了解ruby,那么它类似gem. 对,它就是一个包(package)管理平台,确切的说是 .net平台的包 ...

  5. 项目文件中的已知 NuGet 属性(使用这些属性,创建 NuGet 包就可以不需要 nuspec 文件啦)...

    知道了 csproj 文件中的一些常用 NuGet 属性,创建 NuGet 包时就可以充分发挥新 Sdk 自动生成 NuGet 包的优势,不需要 nuspec 文件啦.(毕竟 nuspec 文件没有 ...

  6. IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

    1.引言 消息是互联网信息的一种表现形式,是人利用计算机进行信息传递的有效载体,比如即时通讯网坛友最熟悉的即时通讯消息就是其具体的表现形式之一. 消息从发送者到接收者的典型传递方式有两种: 1)一种我 ...

  7. DotnetSpider (一) 架构的理解、应用、搭建

    本文连接:http://www.cnblogs.com/grom/p/8931650.html 受业务影响,决定将Downloader单独分层,做出修改. 最近在做爬虫,之前一直在使用 HttpWeb ...

  8. 【EntityFramework 6.1.3】个人理解与问题记录

    前言 又是一个炎热夏日的晚上,开着空调听着音乐又开始了我们今天的博文.此文并不是ROM工具哪家强之类的引战贴,只是本文自己的一点看法和见解,望前辈看官有望斧正 声明 本文欢迎转载,原文地址:http: ...

  9. 一篇万字长文读懂微软PDB、SourceLink——.net core之nuget 包调试

    序言 在大前年,为了说服框架组采用Nuget包的形式分发框架类库,我费了老鼻子的劲也没有取得成功,其中最致命的一个问题是,nuget包不能获得源码调试级的支持,在分发和包的管理形式上其比其他方案都优秀 ...

最新文章

  1. transactionscope 中的异步 处理 异常_.NET Core中TransactionScope事务处理方法介绍及注意事项...
  2. c语言 构造类,C语言之构造类型
  3. 超形象!著名的三角不等式演示动图!
  4. Safari 时间格式转换 NAN 问题
  5. Thinkbayes_Chapter5
  6. 【图像去噪】基于matlab GUI中值+均值+维纳+小波滤波图像去噪【含Matlab源码 800期】
  7. 适合新手——MySQL中基于SQL语言增删改查等基础的练习大汇总
  8. QQ连连看外挂源码-VB源代码
  9. 基于分类分级的医疗临床数据合规共享与安全防护建设实践
  10. Word打开和关闭速度均很慢的解决方法
  11. 笔记本重置找不到恢复环境_Win10重置找不到恢复环境需要安装介质的修复图文教程...
  12. 组队开发最后冲刺周第三次会议
  13. [Acwing] 58周赛 4489. 最长子序列
  14. 带你玩东方系列(视频版)游戏链接
  15. 【深度学习笔记1.1】人工神经网络(内含模型保存与恢复介绍)
  16. 【echarts】xAxis鼠标事件失效问题
  17. 不定积分24个基本公式_干货丨语文阅读理解的24个万能公式,背熟6年一分不扣...
  18. windows下查看端口占用并终止进程
  19. 国内主流常用快递物流查询api接口介绍以及demo分享
  20. 黑莓手机高级使用技巧

热门文章

  1. TCP/IP:IP多播选路
  2. PHP会话控制考察点
  3. [图] DevOps:提速从研发到交付流程
  4. nginx源码学习Unix - Unix域协议
  5. 公司僵尸帐号引发了一系列的入侵事件-细说密码强度验证的重要性
  6. fusioncharts同一页面显示2个仪表盘,且以java字符串作为xml数据
  7. Android Ap 开发 设计模式第七篇:生成器模式
  8. 用PHP实现POP3邮件的收取(一)
  9. 使用ADO.NET的参数集合来有效防止SQL注入漏洞
  10. C# 制作指示灯(经典)