asp.net 5是下一代的asp.net,该版本进行了全部重写以适用于跨平台,新新版本中,微软引入了如下工具与命令:DNVM、DNX、DNU。
DNVM(.NET Version Manager):由于要实现跨平台的目录,微软提供了DNVM功能,DNVM是ASP.NET最底层的内容,他是一组Powershell脚本,用于启动指定版本的ASP.NET运行环境,并且可以在同一台机器的同一时间点上通过使用Nuget工具来管理各种版本的ASP.NET运行环境(DNX),以及进行相应的升级操作。
DNX(.NET Execution Environment):DNX是ASP.NET程序的运行环境,用于启动并运行ASP.NET程序。该运行环境包括了编译系统、SDK工具集、Native CLR宿主环境。可以使用DNVM管理各种版本的DNX,如dnvm list命令可以列出所有可用的DNX环境,而dnvm install 0.1-alpha-build-0446则可以将指定版本的DNX安装到.dnx文件夹,你可以在%USERPROFILE%\.dnx\runtimes 目录下找到已安装所有版本的DNX。不同的操作系统有不同的DNX版本。
dnx.exe:dnx.exe是用于启动自宿主环境(Self-Hosting)的命令行工具,在使用命令行代码进行自宿主环境启动程序时,dnx负责查找并调用CLR Native Host,dnx命令是整个运行环境的入口点,你可以使用dnx run来启动程序。
dnu(DNX Utility):是一个命令行的包管理器,包含在DNX内,所以只要安装了DNX,就可以使用dnu命令, 其可以用于恢复程序包、安装程序包、部署程序包等等,比如把project.json里自定义的程序集自动下载下来进行使用。
DNX架构及运行原理
DNX是ASP.NET程序运行的核心,其遵循如下两个准则:
DNX应该是自包含的,DNX在解析完应用程序依赖树以后才能知道要使用哪个Core CLR包,所以在得到解析树之前,DNX是无法加载任何CLR的,但Roslyn编译器除外。依赖注入(Dependency Injection,简称DI)贯穿着整个系统栈,DI是DNX的一个核心部分,所有DNX上的类库都构建在DI之上。
DNX执行环境的分层架构如下:
Layer 0:Native Process
该层的功能非常简单,主要就是用于查找并调用Layer 1里的CLR Native Host,并将系统相关的参数传递给native host,以便后续使用。目前Windows下使用DNX.exe来处理这个事情,而IIS也提供了一个中介(网站bin目录下提供一个AspNet.Loader.dll)可以将请求转发给Native Host;而Linux和Mac则通过其相应版本的dnx来支持这项功能。
DNX用法:
dnx.exe --lib {paths} --appbase {path} [ProgramName]
--lib {paths}:程序集dll的保存地址(一般是引用的第三方程序集和项目预编译程序集),该地址是Layer 2层的托管代码入口点可以加载程序集的地方。
--appbase {path}:程序保存的目录,默认为%CD%。
[ProgramName]:程序名称,该程序所在的程序集(或者是含有Programe::Main的dll)保存在--lib 路径下,默认值是appbase\project.json里的name。大多数情况下,该名称都是包含着加载链的程序宿主(Microsoft.Net.ApplicationHost)。但是,如果你的程序包含了入口点(Main方法),并被编译到--lib目录下的话,你就可以使用该程序集的名称作为[ProgramName],这种方式将完全忽略加载链并直接启动你的程序。
Layer 1 : CLR Native Host
这一层的内容依赖于你所选择呢CLR版本,该层有如下两个职责:
启动CLR,启动哪个CLR取决于你选择的CLR版本。如果是Core CLR,该层会加载coreclr.dll,配置并启动运行环境,然后创建应用程序域(AppDomain),以便运行所有的托管代码。调用托管代码的入口点(Layer 2),一旦Native Host的入口点返回了该线程,就会把CLR的线程清理干净并关闭,比如,卸载应用程序域(AppDomain)并停止运行环境。
Layer 2:Managed Entry Point
Layer 2层(托管代码入口)是编写托管代码的第一层,其职责如下:
创建LoaderContainer(其包含需要的ILoaders),ILoader负责根据程序集的名称来加载程序集。CLR需要一个程序集的话,LoaderContainer就会使用其ILoader来解析所需要的程序集。从--lib的路径目录下,用根ILoader来加载程序集,并解析其依赖。调用程序的主入口点。
Layer 3:Application host/Application
如果开发人员将整个程序编译成程序集放在libpath目录下,那该层就是你的应用程序了。使用的时候,将含有程序入口点的程序集名称作为[ProgramName]的参数传入即可,Layer 2层会直接调用该程序集。
不过,一般其它情况下,都会使用一个应用程序宿主(Application host)来解析程序的依赖内容并启动运行程序。Microsoft.Net.ApplicationHost是运行环境提供的应用程序宿主,并拥有如下职责: