从本质上讲,按照CLI规范设计的.NET从其出生的那一刻就具有跨平台的基因,这与Java别无二致。由于采用了统一的中间语言,微软只需要针对不同的平台设计不同的虚拟机(运行时)就能弥合不同操作系统与处理器架构之间的差异,但是“理想很丰满,现实很骨感”。在过去十多年中,微软将.NET引入到了各个不同的应用领域,表面上看起来似乎欣欣向荣,但是由于采用完全独立的多目标框架的设计思路,导致针对多目标框架的代码平台只能通过PCL(参考《.NET Core跨平台的奥秘[中篇]:复用之殇》)这种“妥协”的方式来解决。如果依然按照这条道路走下去,.NET的触角延伸得越广,枷锁将越来越多,所以.NET 已经到了不得不做出彻底改变的时刻了。

综上所述,要真正实现.NET 的跨平台伟业,主要需要解决两个问题,一是针对不同的平台设计相应的运行时为中间语言CIL提供一个一致性的执行环境,而是提供统一的BCL以彻底解决代码复用的难题。对于真正跨平台的.NET Core来说,微软不仅为它设计了针对不同平台被成为CoreCLR的运行时,同时还重新设计了一套被称为CoreFX的BCL。

.NET Core跨平台的奥秘[下篇]:全新的布局

如上图所示,NET Core目前支持的AppModel主要有两种,其中ASP.NET Core用于开发服务器Web应用和服务,而UWP(Universal Windows Platform)则用于开发能够在各种客户端设备(Mobile、PC、Xbox、Devices + IOT、HoloLens和Surface Hub等)上以自适应方式运行的Windows 10应用。CoreFX是经过完全重写的BCL,除了自身就具有跨平台执行的能力之外,其提供的API也不再是统一定义在少数几个单一的程序集中,而是经过有效分组之后被定义在各自独立的模块中。这些模块对应着一个单一的程序集,并最终由对应的NuGet包来分发。至于底层的虚拟机,微软则为主流的操作系统类型(Windows、Mac OS X和Linux)和处理器架构(x86、x64和ARM)设计了针对性的运行时,被称为CoreCLR

作为运行时的CoreCLR和提供BCL的CoreFX是.NET Core两根重要的基石,但是就开发成本来看,微软在后者投入的精力是前者无法比拟的。我们知道.NET Core自诞生到现在已经有好些年了,目前的版本还只是到了2.0,从发布进度上显得稍显缓慢,其中一个主要的原因是:重写CoreFX提供的基础API确实是一件繁琐耗时的工程,而且这项工程远未结束。为了对CoreFX提供的BCL有一个大致的了解,我们看看这些常用的基础API究竟定义在哪些命名空间下。

  • System.Collections:定义了我们常用的集合类型。
  • System.Console:提供API完成基本的控制台操作。
  • System.Data:提供用于访问数据库的API,相当于原来的ADO.NET。
  • System.Diagnostics:提供基本的诊断、调试和追踪的API。
  • System.DirectoryServices:提供基于AD(Active Directory)管理的API。
  • System.Drawing:提供GDI相关的API。
  • System.Globalization:提供API实现多语言以及全球化支持。
  • System.IO:提供针对文件输入输出相关的API。
  • System.Net:提供与网络通信相关的API。
  • System.Reflection:提供API以实现与反射相关的操作。
  • System.Runtime:提供与运行时相关的一些基础类型。
  • System.Security:提供与数据签名和加解密相关的API。
  • System.Text:提供针对字符串/文本编码与解码相关的API。
  • System.Threading:提供用于管理线程的API。
  • System.Xml:提供API用以操作XML结构的数据。

我们知道对于传统的.NET Framework来说,承载BCL的API几乎都定义在mscorlib.dll这个程序集中,这些API并不是全部都转移到组成CoreFX的众多程序集中,那些与运行时(CoreCLR)具有紧密关系的底层API被定义到一个叫做System.Private.CoreLib.dll的程序集中,所以下图反映了真正的.NET Core层次结构。我们在编程过程中使用的基础数据类型基本上都定义在这个程序集中,所以目前这个程序集的尺寸已经超过了10M。由于该程序集提供的API与运行时关联较为紧密,较之CoreFX提供的API,这些基础API具有较高的稳定性,所以它是随着CoreCLR一起发布的。

.NET Core跨平台的奥秘[下篇]:全新的布局

虽然我们编程过程中使用到的绝大部分基础类型都定义在System.Private.CoreLib.dll程序集中,但是这却是一个“私有”的程序集,我们可以从其命名看出这一点。我们将System.Private.CoreLib.dll称为一个私有程序集,并不是说定义其中的都是一些私有类型,而是因为我们在编程的过程不会真正引用这个程序集,这与.NET Framework下的mscorlib.dll是不一样的。不仅如此,当我们编写的.NET Core代码被编译的时候,编译器也不会链接到这个程序集上,也就是说编译后生成的程序集中同样也没有针对该程序集引用的元数据。但是当我们的应用被真正执行的时候,所有引用的基础类型全部会自动 “转移” 到这个程序集中。至于如何实现运行过程中的类型转移,其实就是利用了我们上面介绍的Type Forwarding技术。

实例演示:针对System.Private.CoreLib.dll程序集的类型转移

对上面介绍的针对System.Private.CoreLib.dll程序集的类型转移,可能很多人还是难以理解,为了让大家对这个问题具有彻底的认识,我们不妨来做一个简单的实例演示。我们利用Visual Studio创建一个.NET Core控制台应用,并在作为程序入口的Main方法中编写如下几行代码,它们会将我们常用的几个数据类型(System.String、System.Int32和System.Boolean)所在的程序集名称打印在控制台上。

class Program
   2: {
void Main()
   4:     {
string).Assembly.FullName);
int).Assembly.FullName);
bool).Assembly.FullName);
   8:     }
   9: }

相关文章:

  • 2020-07-12
  • 2022-02-17
  • 2022-02-07
  • 2022-12-23
  • 2021-05-26
  • 2021-10-26
  • 2022-12-23
猜你喜欢
  • 2021-05-13
  • 2022-03-09
  • 2021-09-27
  • 2021-09-30
相关资源
相似解决方案