包,元包与框架

本文翻译自 Packages, Metapackages and Frameworks

.Net Core 是一种由 NuGet 包组成的平台。一些产品体验受益于代码包的细粒度定义,而另一些受益于粗粒度的定义,这两种定义都是有用的,不能绝对地说哪个好与不好。因此,为了适应这两种区别,一款好的产品应该可以被拆分成一组一组的细粒度的代码包,这些包之间相互独立,单个代码包的正式的名字叫做“元包”(metapackage)。

每个.Net Core 包都支持运行于多种 .Net 运行时中,这些运行时被称为 “框架”(framework)。其中有的框架是传统框架,例如 net46;而另一些则是新的框架,可以认为它们是“基于包的框架”,这种是框架的另外一种新的定义模型。这些基于包的框架整个都是由包组成的,它们自身也被定义成包,这就在框架与包之间形成了一种比较密切的关系。

.Net Core被分割成为一组包,它们提供了基元类型,以及更高层的数据类型,应用组合类型,以及公共的类库。每一个包都代表着单独的同名程序集,例如,System.Runtime 这个包,就包含了 System.Runtime.dll 这个程序集。

把这些包定义成为细粒度的结构风格,有以下好处:

  • 细粒度的包可以在它自己的开发周期内交付,只需要完成仅对相关的其他有限的包进行测试即可。
  • 细粒度的包可以提供不同的OS与CPU支持。
  • 细粒度的包可以单独依赖于某一个类库。
  • 应用可以变得更小,因为没有引用的包不会变成最终发布的一部分。

上述好处仅适用于某些特定的场合。比如,Net Core 的所有包会在同一个发布周期内提供对同一个平台的支持,在这种情况下,补丁与更新会以小的单独包的形式发布。由于这种小范围的变化,补丁的验证与相关工作,都可以限制到单个平台与类库的需求范围中,这样一来,就可以把工作最小化。

以下是 基于 NuGet 库的 .Net Core 包清单:

  • Sytem.Runtime - 最基础的 .Net Core 包,包含 Object,String,Array, Action 与 IList<T>。
  • System.Collections - 一组基元泛型集合,包含 List<T> 与 Dictionary<K,V>.
  • System.Net.Http - 一组用于 HTTP 网络通信的类型,包含 HttpClient 与 HttpResponseMessage。
  • System.IO.FileSystem - 一组用于读写本地或者网络磁盘存储的类型,包含了 File 与 Dictory 类。
  • System.Linq - 一组对象查询类型,包含了 Enumerable 与 ILookup<TKey, TElement> .
  • System.Reflection - 一组用于类型加载,检查与激活的类型,包含 Assembly, TypeInfo, 与 MethodInfo

包引用在 project.json 文件中定义,在下面的例子中,使用了 System.Runtime 包:

{
"dependencies": {
"System.Runtime": "4.1.0"
},
"frameworks": {
"netstandard1.5": {}
}
}

  

在大部分情况下,你可能不需要直接引用底层的 .Net Core 包,因为引用的包太多了会让你抓狂。所以你只需要引用元包。

元包

元包就是一个 NuGet 包,方便地描述了一组意义相关的包。开发团队利用依赖关系来描述一组包,他们通过这一组包来描述一个框架(framework),然后有选择地发布出去。

引用一个元包,这个操作,实际上添加了对元包中每一个独立包的引用依赖,这意味着这些包中所有的类库(refs 或者 libs)都会在智能感知(IntelliSense)中可用,同时也会发布(lib目录)到你的应用中。

注意: lib 与 ref 指的是 NuGet 包中的相应的文件夹, ref 目录描述的是以元程序集表示的公共API包,lib 目录 包含了这个公共API的在不同框架下的实现。

使用元包有以下好处:

  • 在引用大量细粒度包方面,提供了一种方便的用户体验。
  • 定义了一组经过充分测试与工作良好的包(包括指定的各种版本)。

.Net 标准类库元包:

  • NETStandard.Library - 描述了“.Net 标准类库”的一部分。所有的 .Net 实现(例如, .Net Framework, .Net Core, Mono)都支持 .Net 标准类库,这就是 'netstandard' 框架。

以下是 .Net Core 元包:

  • Microsoft.NETCore.App - 描述了 .Net Core 发行版本的部分类库,也就是 .NETCoreApp 框架。它依赖于NETStandard.Library 这个更小的元包。
  • Microsoft.NETCore.Portable.Compatibility - 一组兼容代理,使基于 mscorlib 的 可移植类库(PCL) 得以运行在 .Net Core上。

元包的引用方法就像普通的 NuGet包一样,在 project.json 中定义。

在下面的例子中, 引用了 NETStandard.Library 这个元包,用来创建一个基于 .Net 运行时的可移植类库。

{
"dependencies": {
"NETStandard.Library": "1.5.0"
},
"frameworks": {
"netstandard1.5": {}
}
}

  

在下面的例子中,引用了 Microsoft.NETCore.App 这个元包,用来创建应用或者是类库,运行于 .Net Core之上,并且充分使用 .Net Core 所有功能。它提供的访问范围,要比 NetStandard.Library 更大。

{
"dependencies": {
"Microsoft.NETCore.App": "1.0.0"
},
"frameworks": {
"netcoreapp1.0": {}
}
}

框架

每一个 .Net Core 包都支持一组框架,在框架文件夹中进行声明(就在前面所说的 lib 与 ref目录中)。框架描述了一组可用的API(以及潜在的其他特性),所以你可以在指定一个目标框架时得到这些功能。当新的API加入时,就会进入版本管理流程。

例如, System.IO.FileSystem 支持以下框架:

  • .NETFramework,版本 4.6
  • .NETStandard,版本 1.3
  • 6种Xamarin 平台 (如, xamarinios10)

很有必要对前两种框架进行对比,因为它们各自代表了一种不同的框架定义方式。

.NETFramework,Version=4.6 这个框架代表了在 .Net Framework 4.6 中可用的API,你可以根据这些API生产自己的类库,引用其中的程序集,并以NuGet包的方发布你的类库,发布后它们会位于lib文件夹下一个名为 net46 的文件夹中。这样,你的

类库就会被那些基于或者兼容 .Net Framework 4.6 的应用程序所使用。这是传统类库的工作方式。

而.NETStandard,Version=1.3这个框架是一个基于包的框架。那些以此框架为目标的包,定义并且实现的API,就组成了这个框架。

可见它们的区别:传统的框架是事先定义好的一个整体,而基于包的框架,则可以对不同的包自由组合。

基于包的框架

框架与包之间的关系是双向的。

首先是为一个给定的框架定义了一组API,如 netstandard1.3。以 netstandard1.3 为目标的包(或者兼容框架,如netstandard1.0)定义了哪些API是可以使用的,听起来像是循环定义,然而并不是。从 “基于包的”这个词本身的角度来讲,框架的API定义是来自于包的,框架本身并不定义任何API。

其次,是这个双向关系中的资产选择。包内部可以含有不同框架的资产,对于一组包或者元包的引用,框架需要决定它应选择哪些资产,例如,是 net46 还是 netstandard1.3。对于交叉资产来说,这个非常重要,例如,一个 net46 的资产可能并不会与 .Net Framework 4.0 或者 .Net Core 1.0 兼容。


你可以在上图中看到这种关系,API 选择 框架 作为目标,并且API定义了框架, 而框架用于资产选择,资产实现了API。

这里出现了一个有趣的问题:框架定义的结束之处,正是消费开始的地方。可以把框架看成是由 project.json 文件给出的功能定义,你所依赖的东西创建了实际上的框架,这个框架独立于那些已经发布出来的完整框架的依赖项。(译者注:可以这么理解,

框架的实际实现取决于你在 project.json 中引用的东西,可能你并不会引用所有的包,所以你所依赖的包是官方框架的全部包的一个子集。)

在.Net Core基础之上,基于包的框架主要有两个:

  • netstandard
  • netcoreapp

.NET Standard

.NET 标准框架(netstandard)意指基于 .Net 标准类库所定义与构建的API。如果你所构建的类库将会用于多种运行平台,应该以基于netstandard进行构建,这样类库就会支持任何一种 兼容 .Net 标准的运行时,比如 .Net Core, .Net Framework以及 Mono/Xamarin。这些运行时中的每一处都支持一种或几种 .Net 标准,至于到底支持哪个版本,则取决于具体实现。

元包 NETStandard.Library 的目标框架是 netstandard。要以 netstandard 为目标框架,最常见的方法是引用此元包。它定义与提供了约40个.Net类库,并与.Net 标准类库所定义的API相关联。你可以引用基于 netstandard 开发的第三方包来使用第三方API。

一个给定的 NETStandard.Library 版本,总是与 netstandard 所公开的最高版本相匹配。 project.json 文件中对于框架的引用,主要是用来从此框架中选择正确的资产。因此,假如定义了 netstandard1.5,就需要 其中的dll资产,而不是 netstandard1.4,或者 net46。

{
"dependencies": {
"NETStandard.Library": "1.5.0"
},
"frameworks": {
"netstandard1.5": {}
}
}

  

这个 project.json 文件中所引用的 框架与元包 并不需要严格匹配,例如下面的 project.json 也是正确的:

{
"dependencies": {
"NETStandard.Library": "1.5.0"
},
"frameworks": {
"netstandard1.3": {}
}
}

  

把构建目标设置为 netstandard1.3 却使用 NETStandard.Library 的 1.5 版本,似乎有点奇怪。然而这是一个合法的用例,因为元包支持更老的 netstandard 版本。可能恰好 你使用了 1.5.0 的元包版本来开发你所有的类库,然后运行于多种版本的 netstandard,在这种情况下,你只需要重新加载 NETStandard.Library 1.5.0 即可,并不需要加载早期版本。

反之则并不成立:把 netstandard1.5 作为运行目标,却使用 NETStandard.Library 的 1.3.0 版本来开发你的类库:你不能够把更高版本的框架作为开发目标,却使用更低版本的元包。元包资产的版本管理机制,与框架的最高版本的定义相匹配。借助于版本管理机制,NETStandard.Library 的第一个版本是 v1.5.0,它包含了 netstandard1.5 的资产。而上面例子中的 v1.3.0 版本,只是为了举例方便,实际上并不存在。

译者注:这一段的各种名词相互绕来绕去,会把人绕晕。举个例子就明白了:因为类库总是向下兼容的,1.5 的实现必然包含了1.3的所有定义,1.5 版本的元包,是可以运行于 1.3 版本的框架之上。

然而这与我们的直觉经验不符,因此作者说看起来很奇怪,因为你在 Win7 上开发的程序(依赖高版本元包),很可能不支持运行在 XP 系统上(低版本框架)。

但是为什么在神奇的 .Net Core 的世界中,这个现象就发生了呢?

这是由 .Net Core 的版本管理机制所决定的。文中并没有给出来具体的解释。关于版本管理,有另外一篇文章会介绍,稍后翻译。

.NET Core Application

.NET Core Application 框架(netcoreapp) 意为: 包与相关的API是 基于.Net Core 特定发布版本以及它所提供的控制台程序模型。.Net Core应用程序必须使用这个框架,因为必须要使用其中的控制台程序模型。同时只运行于 .Net Core 平台的类库也应使用这个模型。使用这框架以后,应用程序(exe)与类库(dll)将只能够运行于.Net Core平台上。(老外好啰嗦啊) 元包 Microsoft.NETCore.App 的目标框架是 netcoreapp 。此元包提供了约 60 个类库,其中大约 40 个是由 NETStandard.Library 提供的,另外20个是由 Microsoft.NETCore.App 自己实现的(addition)。如果你开发的类库的目标框架是 netcoreapp 或其兼容框架(如netstandard),则可以使用 Microsoft.NETCore.App 的这些20个额外类库(addition),来调用这些额外的API。

译注:addition,是指由 Microsoft.NETCore.App 在 NETStandard.Library 基础之上的额外实现,约20个类库。在从传统 Framework迁移过来的代码中,如果你使用了 NETStandard.Library ,可能会出现不识别类或者方法的情况,很有可能是因为这些不识别的部分实现在这20个addition中,改为引用 Microsoft.NETCore.App 可能会解决问题。

由 Microsoft.NETCore.App 额外实现的大部分类库,也可以运行于 其他的 netstandard 框架,如果这些框架满足了它们所依赖的类库的运行环境的话。这意味着 运行于 netstandard 框架的类库也引用这些额外包作为依赖项。

译注:这段话也比较晦涩,再举例子说明。例如 Microsoft.NETCore.App 1.5 (简称App1.5)是 在 NETStandard.Library 1.5 (简称Lib1.5)之上实现了额外20个包(Add20),即 App1.5 = Lib1.5 + Add20。 前面说 Lib1.5 可以运行于框架 netstandard 1.5(简称 Std1.5),以及 Std1.3 之上,如果这个 Add20 也可以运行于 Lib1.3 的话,那么就可以得到 App1.5 也可以运行于 Lib1.3。

.Net Core 中的包、元包与框架(Packages, Metapackages and Frameworks)的更多相关文章

  1. .net core中的那些常用的日志框架(NLog篇)

    前言 咱们上回讲到,.net core中内置的Logging日志框架的使用,以及浅显的讲解,接下来,给大家介绍一个第三方日志框架(NLog). NLog简介 NLog是适用于各种.NET平台(包括.N ...

  2. .net core中的那些常用的日志框架(Serilog篇)

    前言 上文说到Nlog日志框架,感觉它功能已经很强大,今天给大家介绍一个很不错的日志框架Serilog,根据我的了解,感觉它最大的优势是,结构化日志,它输出的日志是Json的格式,如果你使用的是Mon ...

  3. .net core中的那些常用的日志框架(Logging篇)

    前言 日志,在我们每个项目中是必不可少的,它不仅能在调试的时候测试数据,而且在项目上线,也是我们排查错误的得力助手,那我就能谈谈,用的多的几个日志框架吧!如果有不对的地方,欢迎来指教错误,谢谢! As ...

  4. 在.NET Core中使用Exceptionless分布式日志收集框架

    一.Exceptionless简介 Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,ASP.NET Core,Web Api,Web Forms,WPF, ...

  5. .NET Core中的包、元包与框架

    本文为翻译文章,原文:Packages, Metapackages and Frameworks .NET Core是一个由NuGet包组成的平台.一些产品受益于细粒度包的定义,也有一些受益于粗粒度包 ...

  6. 大话DI依赖注入+IOC控制反转(二) 之 浅析.Net Core中的DI与IOC

      转发时请注明原创作者及地址,否则追究责任.原创:alunchen 在上一篇文章中,我们聊了很多关于定义的方面,比较孤燥,下面我们结合.Net Core聊一下依赖注入&控制反转. 三种对象生 ...

  7. .Net Core 学习笔记1——包、元包、框架

    .Net Core 是由NuGet包(package)组成的平台. 一起使用的多个包的集合:元包(Metapackage) package 包 (对应以前的程序集概念) Framework 框架 as ...

  8. 解决 .net core 中 nuget 包版本冲突问题

    今天在一个 asp.net core 项目中遇到了 nuget 包版本冲突的问题,错误信息如下: Version conflict detected for Microsoft.AspNet.WebA ...

  9. .NET Core中创建和使用NuGet包

    在.NET Core的项目中,如果我们要在项目中引用其它DLL文件,不应该直接在项目引用中添加DLL文件(虽然在.NET Core项目中也可以这么做),建议是去直接下载DLL文件所属的NuGet包.这 ...

随机推荐

  1. iOS常用的存储方式介绍

    在iOS App开发过程中经常需要操作一些需要持续性保留的数据,比如用户对于App的相关设置.需要在本地缓存的数据等等.本文针对OC中经常使用的一下存储方式做了个整理. 常用的存储工具/方式: NSU ...

  2. UVA 816 - Abbott&#39;s Revenge(BFS)

    UVA 816 - Abbott's Revenge option=com_onlinejudge&Itemid=8&page=show_problem&category=59 ...

  3. Computer Science Theory for the Information Age-4: 一些机器学习算法的简介

    一些机器学习算法的简介 本节开始,介绍<Computer Science Theory for the Information Age>一书中第六章(这里先暂时跳过第三章),主要涉及学习以 ...

  4. PAT 1004

    1004. Counting Leaves (30) A family hierarchy is usually presented by a pedigree tree. Your job is t ...

  5. Mac电脑没有声音,苹果电脑没有声音怎么办

      对于使用 Windows 系统电脑的小伙伴来说,可能有很多人会遇到电脑没有声音的问题.苹果 Mac 电脑也会出现没有声音的问题,不过相对较少.这里以我遇到的一个没有声音的问题为例,简单介绍处解决的 ...

  6. mysql自动备份策略

    目标:每7天做一个完整备份,每天做一份binlog日志,第二周将之前的备份删除并产生新的完整备份和binlog日志,备份要求每天2:00自动完成 mysql 版本:mysql5.5 1.开启binlo ...

  7. 使用GPS经纬度定位附近地点(某一点范围内查询)

    需要手机查找附近N米以内的商户,致想法是已知一个中心点,一个半径,求圆包含于圆抛物线里所有的点,经纬度是一个点,半径是一个距离,不能直接加减,下面提供C#的解决方法 数据库中记录了商家在百度标注的经纬 ...

  8. Google Code Jam 2009, Round 1C C. Bribe the Prisoners (记忆化dp)

    Problem In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. ...

  9. angular 项目回顾

    从学习angular,到实际项目开发不到一周,完全是边写边学呀,都是为了项目,已使用angular 开发了两个项目了,有些技术当时只是会用,都没好好回顾一下,现在有时间回顾一下,项目中用到的一些指令, ...

  10. jquery中ajax向action传递对象参数,json ,spring注入对象

    首先,我这个程序的框架是spring+struts2+hibernate. 后端的action的需要接受从前端传进来的参数,由spring的注入,可知,如果前端用的是form的话,只需要在每个inpu ...