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

本文为翻译文章,原文:Packages, Metapackages and Frameworks

.NET Core是一个由NuGet包组成的平台。一些产品受益于细粒度包的定义,也有一些受益于粗粒度包的定义。为了适应这种二重性,.NET Core平台被分为一组细粒度的包(package)以及一些被称为元包(metapackage)的较粗粒度的包。

每一个.NET Core包支持多个.NET运行时,它们代表着不同的框架。这些框架既包括传统的.NET Framework(如net4.6),也包含基于包的新框架,这些新框架建立了定义框架的新模型。这些基于包的框架完全由包定义而成,包与框架之间形成较强的关联关系。

.NET Core由一组包构成,这些包提供了基元类型、高级数据类型、应用程序组成类型和一些常见的实用工具。每一个包表示一个和包同名的程序集,如, System.Runtime包中含有System.Runtime.dll程序集。

定义细粒度的包有如下好处:

  • 细粒度的包在开发、测试过程中与其它包的关联有限
  • 细粒度的包可以提供对不同操作系统和CPU的支持
  • 细粒度的包可以只依赖某个特定的库
  • 在发布应用时,未被引用的包不会成为应用的一部分,因此应用程序会有更小的体积

有些细粒度包的优点只会在特定场景中表现出来。如,通常.NET Core 的所有包会在同一计划内提供对同一平台的支持。这种情况下,补丁会以小的单个更新包的形式发布和安装。由于这种小范围的变化,验证补丁是否可用所花费的时间,可以限制到对单个库的需求中。

下面列出了.NET Core平台上的一些关键NuGet包:

通常,与逐个添加项目所需要的包相比,使用元包的方式来添加项目依赖更加容易,因为元包是一组常用包的集合。当你需要某个单独的包时,你可以使用下面例子中添加对System.Runtime引用的方式来添加对它的引用。

<Project Sdk="Microsoft.NET.Sdk"> 
    <PropertyGroup> 
        <TargetFramework>netstandard1.6</TargetFramework> 
    </PropertyGroup> 
    <ItemGroup> 
        <PackageReference Include="System.Runtime" Version="4.3.0" />        
    </ItemGroup>
</Project>

元包

元包是一个NuGet包约定,用于描述一组放在一起有意义的包。 这些包是通过依赖项来被描述的。可以通过为这组包指定一个框架来建立一个框架(这话拗口,原文:They can optionally establish a framework for this set of packages by specifying a framework.)。

以前版本的.NET Core工具(project.json和基于csproj的工具)在默认情况下会指定一个框架和元包 。不过,现在,元包被目标框架隐式引用,这样一来每个元包都和目标框架关联在一起。例如,netstandard1.6框架引用了NetStandard.Library 1.6.0元包。类似的,netcoreapp1.1框架引用了Microsoft.NETCore.App 1,1.0元包。更过信息,参考.NET Core SDK中元包的隐式引用

指定一个框架会隐式实现对元包引用,同时也会添加对元包依赖项的引用。这样,元包中的所有类库都能够被IDE智能感知,也可以被打包到你的应用中。

使用元包有以下好处:

  • 在引用大量细粒度包时有更好的用户体验
  • 定义了一组经过测试且运行良好的包(包括指定的各种版本)

.NET 标准库元包(.NET Standard Library metapackage):

  • NETStandard.Library - 表示.NET标准类库的一部分。所有的.NET 实现(如,.NET Framework、.NET Core 和 Mono)都支持.NET 标准类库。NETStandard.Library用于建立netstandard框架。

.NET Core核心元包有:

框架

每个.NET Core包都支持多个运行时框架。这些框架描述一组可用于你所指定的框架的API(和一些其它特征)。当加入新的API时,这些框架的版本号也会发生相应的变化。

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

  • .NETFramework,Version=4.6
  • .NETStandard,Version=1.3
  • 6 Xamarin platforms (如, xamarinios10)

这些运行时框架使用不同的方式进行框架的定义,对比学习前两个框架会大有裨益。

.NETFramework,Version=4.6框架表示可用于.NET Framework 4.6之上的API。

我们可以编写基于.NET Framework 4.6引用程序集的库,并以NuGet 包的方式在 net46 lib 文件夹中发布这些库。这些库可用于那些基于或兼容.NET Framework 4.6的应用。这是所有框架的传统工作方式。

.NETStandard,Version=1.3是一个基于包的框架。它依靠包来定义目标框架以及公开该框架的API。

基于包的框架

包与框架之间是双向关系。首先为一个给定框架定义可用的API,如netstandard1.3。用于netstandard1.3框架(或兼容框架,如netstandard1.0)的软件包定义该框架上可用的API。这看起来像是循环定义,但不是。基于包的框架上的API由包来定义,框架本身并不定义任何API。

其次,是这种双向关系中的第二部分,资产选择(asset selection)。包可以包含用于多框架的资产。对于一组包或者元包的引用,框架需要决定选择哪种资产,如net46netstandard1.3。选择正确的资产是很重要的。如,一个net46资产可能不兼容.NET Framework 4.0 或 .NET Core 1.0

上图描述了这种双向关系。API指定并定义框架。框架选择资产。资产提供具体的API实现。

.NET Core平台上使用的两个主要的基于包的框架是:

  • netstandard
  • netcoreapp

.NET 标准

.NET标准(目标框架名:netstandard)框架是指基于.NET标准库(.NET Standard Library)而定义和创建的API。这些库计划支持以.NET 标准框架为目标框架的多个运行时。它们支持任何与.NET标准(.NET Standard )兼容的运行时,如.NET Core、.NET Framework和Mono/Xamarin(下面附上一张图作为补充)。每个运行时都支持一组.NET Standard版本,具体取决于它们所要实现的API。

标准框架隐式引用NETStandard.Library元包。如,下面的MSBuild项目文件显示了当前项目的目标框架是netstandard1.6,这个框架引用.NET Standard Library version 1.6元包。

<Project Sdk="Microsoft.NET.Sdk"> 
    <PropertyGroup> 
        <TargetFramework>netstandard1.6</TargetFramework> 
    </PropertyGroup>
</Project>

但是,框架和项目文件中所引用的元包无需一一对应,你可以在项目文件中使用<NetStandardImplicitPackageVersion>来制定一个版本号低于元包版本号的框架。如,下面的配置框文件是有效的。

<Project Sdk="Microsoft.NET.Sdk"> 
    <PropertyGroup> 
        <TargetFramework>netstandard1.3</TargetFramework> 
    </PropertyGroup>
    <ItemGroup> 
        <NetStandardImplicitPackageVersion Include="NetStandardLibrary" Version="1.6.0" /> 
    </ItemGroup>
</Project>

netstandard1.3框架使用NETStandard.Library 1.6.0可能看起来比较奇怪。但这种使用情况是合法的,因为元包向后兼容低版本的netstandard。若你已经将1.6.0版本的元包并将其应用到自己的面向多个netstandard版本的库中。通过这种向后兼容的方式,你只需还原(restore)NETStandard.Library1.6.0而无需关注更早的版本。

与此相反,netstandard1.6引用NETStandard.Library 1.3.0是不被允许的,因为低版本的元包不会公开任何构建高版本框架的资产。元包资产的版本控制使得元包和它们所描述的框架的最高版本相匹配。借助版本控制,NETStandard.Library的第一个版本是1.6.0,它包含netstandard1.6的资产。上述例子中的1.3.0版本只是为了举例需要,事实上它并不存在。

.NET Core 应用

.NET Core 应用(目标框架:netcoreapp)框架表示.NET Core 发行版和它提供的控制台应用程序模型附带的包和相关API。.NET Core应用必须使用该框架,因为它基于的控制台应用模型的库仅仅运行于.NET Core框架上。使用这个框架可以限制应用和库只运行于.NET Core之上。

Microsoft.NETCore.App元包的目标框架是netcoreapp。它支持对约60个库的访问,其中约40个由NETStandard.Library提供, 还有约20个其它(标准库以外的)附加库。你可以引用基于或兼容netcoreapp,如netstandard的附加库,以获取对附加库API的访问。

大多数由Microsoft.NETCore.App提供的附加库,如果这些库可以很好的依赖其它的netstandard库的话,它们也可用于netstandard。这意味着netstandard libraries可以添加对这些包的引用。

结语

由于水平有限,翻译内容难免有错误和不足之处,希望大家提出改进意见。文章最后是自己建立.NET Core控制台程序的引用包截图和项目配置文件,大家可以作为辅助理解文章内容的补充材料。

项目包引用

packages.PNG

项目文件

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" />
    <PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.3.0" />
  </ItemGroup>
</Project>

版权声明

本文为作者原创,版权归作者雪飞鸿所有。 转载必须保留文章的完整性,且在页面明显位置处标明原文链接

如有问题, 请发送邮件和作者联系。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ASP.NETCore

查看.NET Core源代码通过Autofac实现依赖注入到Controller属性

  在之前的文章【ASP.NET Core 整合Autofac和Castle实现自动AOP拦截】中,我们讲过除了ASP.NETCore自带的IOC容器外,如何使...

58970
来自专栏Rovo89

如何让sublime text 2可以支持C语言的编译和run

18240
来自专栏『不羁阁』 | 行走少年郎专栏

iOS多线程:『pthread、NSThread』详尽总结

22050
来自专栏逸鹏说道

Ubuntu18.04下给Jupyter-NoteBook设置默认工作路径

生成配置文件:jupyter-notebook --generate-config

24030
来自专栏张善友的专栏

Jayrock: JSON and JSON-RPC for .NET

mojoPortal 项目中使用Joyrock和MagicAjaxNET,他没有使用Asp.net ajax ,是因为mojoPortal是一个运行在Windo...

26380
来自专栏张善友的专栏

Castle.MVC框架介绍

Castle.MVC目前还在Castle的Sandbox中,只是在源代码管理中有,还没有向外发布版本,这里介绍多时Web的MVC,和Castle的MonoRai...

24580
来自专栏程序员互动联盟

【编程基础】跟我学创建Windows动态库

如何简单快速创建Win32平台下的动态链接库?但是有的创建出来用C/C++调用时没有问题,但是在其它编程语言调用时可能会出现问题,下面我们就按四个傻瓜式的步骤创...

30190
来自专栏calvin

Microsoft.AspNet.Identity 自定义使用现有的表—登录实现

Microsoft.AspNet.Identity是微软新引入的一种membership框架,也是微软Owin标准的一个实现。Microsoft.AspNet....

13120
来自专栏逸鹏说道

图片在保存的时候===》出现这个异常:GDI+ 中发生一般性错误

异常处理汇总-后端系列 http://www.cnblogs.com/dunitian/p/4523006.html ? 一般这种情况都是没有权限,比如目录没有...

39080
来自专栏大内老A

“前.NET Core时代”如何实现跨平台代码重用 ——程序集重用

除了在源代码层面实现共享(“前.NET Core时代”如何实现跨平台代码重用 ——源文件重用)之外,我们还可以跨平台共享同一个程序集,这种独立于具体平台的“中性...

20680

扫码关注云+社区

领取腾讯云代金券