zoukankan      html  css  js  c++  java
  • .Net Core 中的包、元包与框架(Packages, Metapackages and Frameworks)

    包,元包与框架

    本文翻译自 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。

  • 相关阅读:
    HDU 5585 Numbers
    HDU 3308 LCIS
    POJ 2991 Crane
    POJ 1436 Horizontally Visible Segments
    POJ 3667 Hotel
    HaiHongOJ 1003 God Wang
    【SDOI 2008】 递归数列
    5月19日省中提高组题解
    【HDU 1588】 Gauss Fibonacci
    【POJ 3233】Matrix Power Series
  • 原文地址:https://www.cnblogs.com/liuweizzuie/p/5827030.html
Copyright © 2011-2022 走看看