🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
ASP.NET Core应用本质上就是一个由中间件构成的管道,承载系统将应用承载于一个托管进程中运行起来,其核心任务就是将这个管道构建起来。在ASP.NET Core的发展历史上先后出现了三种应用承载的编程方式,而且后一种编程模式都提供了针对之前编程模式的全部或者部分兼容,这就导致了一种现象:相同的更能具有N种实现方式。对这个发展历程不是特别了解的读者会有很多疑问?为什么这么多不同的编程模式都在作同一件事?它们之间的有什么差别之处?为什么有的API在最新的Minimal API又不能用了呢?[本文部分内容来源于《ASP.NET Core 6框架揭秘》第15章]
目录一、应用承载过程中需要哪些初始化工作?
二、第一代应用承载模型 基本编程模式 利用环境变量和命令行参数 承载环境设置方法 使用Startup类型
三、第二代应用承载模型 基本编程模式 承载环境设置方法 针对IWebHostBuilder的适配 Startup构造函数注入的限制
一、应用承载过程中需要哪些初始化工作?
我们所谓的应用承载(Hosting)本就是将一个ASP.NET Core应用在一个具体的进程(Self-Host进程、IIS工作进程或者Windows Service进程等)中被启动的过程,在这个过程中需要利用提供的API完成一些必要的初始化工作。由于ASP.NET Core应用本质上就是一个由中间件构成的管道,所有整个初始化过程的目的就是为了构建这一中间件管道,毫不夸张地说,构建的中间件管道就是“应用”本身,所以“中间件注册”是最为核心的初始化工作。由于依赖注入的广泛应用,中间件的功能基本都依赖于注入的服务来完成,所以将依赖服务注册到依赖注入框架是另一项核心的初始化工作。
和任何类型的应用一样,ASP.NET Core同样需要通过配置来动态改变其运行时行为,所以针对配置的设置也是并不可少的。一个ASP.NET Core应用的配置分为两类,一种是用在中间件管道构建过程中,也就是应用承载过程中,我们将其称为“承载配置(Hosting Configuration)”。另一类配置则被用来控制中间件管道处理请求的行为,正如上面所说,中间件管道就是应用本身,所以这类配置被称为应用配置(App Configuration)。承载配置中有一个重要的组成部分,那就是描述当前的承载环境(Hosting Environment),比如应用的标识、部署环境的名称、存放内容文件和Web资源的目录等。承载配置最终会合并到应用配置中。
综上所示,ASP.NET Core应用承载的编程模型主要完成如下几种初始化工作,这些工作都具有N种实现方法。在接下来的内容中,我们将逐个介绍在三种不同的应用承载方式中,这些功能都有哪些实现方式。
- 中间件注册
- 服务注册
- 承载配置的设置
- 应用配置的设置
- 承载环境的设置
二、第一代应用承载模型
ASP.NET Core 1.X/2.X采用的承载模型以如下图所示的IWebHostBuilder和IWebHost为核心。IWebHost对象代表承载Web应用的宿主(Host),管道随着IWebHost对象的启动被构建出来。IWebHostBuilder对象作为宿主对象的构建者,我们针对管道构建的设置都应用在它上面。
基本编程模式
现在我们将针对上述5种初始化设置放在一个简单的演示实例中。该演示实例会注册如下这个FoobarMiddleware中间件,后者利用注入的IHandler服务完成请求的处理工作。作为IHandler接口的默认实现类型,Handler利用构造函数注入的IOptions对象得到配置选项FoobarbazOptions,并将其内容作为请求的响应。
public class FoobarMiddleware
{
private readonly RequestDelegate \_next;
public FoobarMiddleware(RequestDelegate \_) { }
public Task InvokeAsync(HttpContext httpContext, IHandler handler) => handler.InvokeAsync(httpContext);
}
public interface IHandler
{
Task InvokeAsync(HttpContext httpContext);
}
public class Handler : IHandler
{
private readonly FoobarbazOptions \_options;
private readonly IWebHostEnvironment \_environment;
public Handler(IOptions optionsAccessor, IWebHostEnvironment environment)
{
\_options = optionsAccessor.Value;
\_environment = environment;
}
public Task InvokeAsync(HttpContext httpContext)
{
var payload = @$"
Environment.ApplicationName: {\_environment.ApplicationName}
Environment.EnvironmentName: {\_environment.EnvironmentName}
Environment.ContentRootPath: {\_environment.ContentRootPath}
Environment.WebRootPath: {\_environment.WebRootPath}
Foo: {\_options.Foo}
Bar: {\_options.Bar}
Baz: {\_options.Baz}
";
return httpContext.Response.WriteAsync(pa