编程博客
002、修改Nuget包位置
001、C#常用的单词
003、收藏的书签
回家准备
004、ASP.NET Core 3.0 gRPC
001、ASP.NET Core 3.0 使用gRPC
002、ASP.NET Core 3.0 gRPC 双向流
003、ASP.NET Core 3.0 gRPC 身份认证和授权
005、飞牛NAS
001、 FnOS飞牛系统实用配置1-应用远程访问(迅雷)
006、DeepSeek
001、DeepSeek 使用指南
007、并发编程
01、并发编程 - 死锁的产生、排查与解决方案
02、并发编程 - 初识线程
03、并发编程 - 线程浅试
04、并发编程 - 线程同步(一)
05、并发编程 - 线程同步(二)
06、并发编程 - 线程同步(三)之原子操作 Interlocked 简介
07、并发编程 - 线程同步(四)之原子操作 Interlocked 详解一
08、并发编程 - 线程同步(五)之原子操作 Interlocked 详解二
09、并发编程 - 线程同步(六)之锁 lock
008、启动项
03、应用--Program 中的 WebApplication
02、主机--Host
01、Program 文件的作用
04、控制反转 IOC 与依赖注入 DI
05、中间件
06、Logger 原理及配置 Log4Net
07、ElasticSearch
本文档使用 MrDoc 发布
-
+
首页
03、应用--Program 中的 WebApplication
在 6.0,微软团队对于 NetCore 做了很大的改变,其中有一个改变就是推出了新的托管模型--最小托管模型,使用该模型可以创建最小的 web 应用。(最小 webapi 请查看[官网](https://learn.microsoft.com/zh-cn/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0&tabs=visual-studio)) **需要掌握:** * [ ] 什么是最小托管模型?以及他的作用 * [ ] 什么是 WebApplication 和 WebApplicationBuilder?他们和 Host 的区别是什么 * [ ] WebApplication 代码上以及对应逻辑上的构造流程,能简单描述就好了 * [ ] WebApplication 的六个属性以及其作用,为什么需要这 6 个属性? * [ ] WebApplicationBuilder 的作用 * [ ] WebApplication 的 6 个属性以及继承 4 个接口有什么用 ## **构造流程**[#](https://www.cnblogs.com/boise/p/18002731#%E6%9E%84%E9%80%A0%E6%B5%81%E7%A8%8B) 得到 `WebApplicationBuilder构造器` -> 配置服务 -> `build()` 方法得到 `WebApplication对象` -> 配置中间件 -> 运行主机 ```C# // 得到应用构造器:WebApplicationBuilder var builder = WebApplication.CreateBuilder(args); // 配置日志 builder.Logging.AddLog4Net("ConfigFile/log4net.config"); // 得到应用:WebApplication var app = builder.Build(); // 配置中间件 app.UseStaticFiles(); // 运行主机 app.Run(); ``` 你可能在疑惑,在 3.0 至 5.0 的版本都是直接调用 `Host.CreateDefaultBuilder()` 方法得到 `HostBuilder构造器`,然后调用 `ConfigureWebHostBuilder()` 配置 `WebHost`,然后在上面配置一些服务,构建然后运行。而 6.0 使用 `WebApplication.CreateBuilder(args)` 方法得到的是一个 `WebApplicationBuilder` 构造器,然后构建运行,他们有什么区别吗? 答:没什么区别,流程都是一样的,`WebApplication` 对主机和服务做了一个更进一步的封装,使得更加方便配置和学习,而且额外暴露 2 个 `Host属性` 和 `WebHost属性` 用来配置(这 2 个属性也是方便之前的版本迁移到 6.0 的关键)。举个很简单的例子 | 区别 | 在 3.0 至 5.0 的版本中 | 6.0 版本中 | | ---------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 中间管道的配置 | 必须放在 Startup.cs 类中的 Configure 方法中,或者通过 ConfigureWebHostDefaults 中的 webBuilder 来配置服务 | 通过调用 app.UseXXXX 来配置 | | 路由中间件 | 使用 app.UseRouting()之后才能 app.UseEndpoints() | 因为 WebApplication 继承了 WebIEndpointRouteBuilder 可以直接将路由,而无需显式调用 [UseEndpoints](https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.builder.endpointroutingapplicationbuilderextensions.useendpoints) 或 [UseRouting](https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.builder.endpointroutingapplicationbuilderextensions.userouting)。 | | | | | ## 按照上方 Program.cs 流程顺序介绍相关类和方法[#](https://www.cnblogs.com/boise/p/18002731#%E6%8C%89%E7%85%A7%E4%B8%8A%E6%96%B9programcs%E6%B5%81%E7%A8%8B%E9%A1%BA%E5%BA%8F%E4%BB%8B%E7%BB%8D%E7%9B%B8%E5%85%B3%E7%B1%BB%E5%92%8C%E6%96%B9%E6%B3%95) ### 1. CreateBuilder(args) 方法:[#](https://www.cnblogs.com/boise/p/18002731#1-createbuilderargs-%E6%96%B9%E6%B3%95) 使用默认值来生成构造一个 `WebApplicationBuilder对象` 该方法有 3 个重载: * `WebApplication.CreateBuilder()`:使用预配置的默认值来构造; * `WebApplication.CreateBuilder(String [])`:根据传入的命令行参数初始化; * `WebApplication.CreateBuilder(WebApplicationOption)`:根据传入的预配置来构造; ```C# public class WebApplicationOptions { public WebApplicationOptions(); // 命令行参数 public string[]? Args { get; init; } // 环境名称。 public string? EnvironmentName { get; init; } // 应用程序名称。 public string? ApplicationName { get; init; } // 内容根路径。 public string? ContentRootPath { get; init; } // Web 根路径。 public string? WebRootPath { get; init; } } ``` #### WebApplicationBuilder 类:[#](https://www.cnblogs.com/boise/p/18002731#webapplicationbuilder%E7%B1%BB) 要创建一个 `WebApplication对象`,需要一个 `IHost对象`,`IHost对象` 是通过 `IHostBuilder创建` 的,而 `WebApplication` 需要 `WebApplicationBuilder` 来构建,所以 `WebApplicationBuilder` 还需要一个 IHostBuilder 对象,我们针对 `WebApplication` 的一切配置,最终都会转移到这个对象上面才能生效,所以这就是为什么 `WebApplicationBuilder` 提供了这 6 个属性的原因。 ##### 构造函数 当通过调用 `WebApplication.CreateBuilder()` 方法的时候,根据命令行的参数传给 `WebApplicationBuilder` 的构造函数,而 `WebApplicationBuilder` 的构造函数内部会做: 1. 创建 `HostBuilder _hostBuilder` 类。 2. 创建 `BootstrapHostBuilder` 对象,调用拓展方法 `ConfigureWebHostBuilder()` 和 `ConfigureDefaults()` 方法,将初始化的设置和服务收集起来,然后把收集到的服务和配置注入到 `Services成员属性` 和 `Configure成员属性` 中。 3. 然后会创建承载托管环境的 `IWebHostEnvironment`,对于 `Environment成员属性` 初始化。 4. 调用 `Apply()` 方法得到 `HostBuilderContext上下文`。 5. 使用 `HostBuilderContext` 的 `WebHostBuilderContext`,创建 `ConfigureWebHostBuilde` r 和 `ConfigureHostBuilder` 并赋值给 `WebHost和Host属性`。初始化 `Logging属性`。 6. 得到一个 `Configure、Environment、WebHost、Host、Logging属性` 都被初始化的 `WebApplication对象`。 *WebApplicationBuilder 构造函数源码* ```c# public class WebApplicationBuilder { private readonly HostBuilder _hostBuilder = new HostBuilder(); private WebApplication _application; // 提供应用程序正在运行的Web托管环境的信息 public IWebHostEnvironment Environment { get; } // 提供应用程序所需要的服务,即依赖注入容器 public IServiceCollection Services { get; } // 提供应用程序所需要的配置 public ConfigurationManager Configuration { get; } // 提供日志记录 public ILoggingBuilder Logging { get; } // 配置WebHost服务器特定属性,实现IWebHostBuilder public ConfigureWebHostBuilder WebHost { get; } // 配置Host特定属性,实现IHostBuilder public ConfigureHostBuilder Host { get; } public WebApplicationBuilder(WebApplicationOptions options) { //创建BootstrapHostBuilder并利用它收集初始化过程中设置的配置、服务和针对依赖注入容器的设置 var args = options.Args; var bootstrap = new BootstrapHostBuilder(); bootstrap .ConfigureDefaults(null) // 此处用于中间件的注册 .ConfigureWebHostDefaults(webHostBuilder => webHostBuilder.Configure(app =>app.Run(_application.BuildRequestDelegate()))) .ConfigureHostConfiguration(config => { // 添加命令行配置源 if (args?.Any() == true) { config.AddCommandLine(args); } // 将WebApplicationOptions配置选项转移到配置中 Dictionary<string, string>? settings = null; if (options.EnvironmentName is not null) { (settings ??= new())[HostDefaults.EnvironmentKey] = options.EnvironmentName; } if (options.ApplicationName is not null){ (settings ??= new())[HostDefaults.ApplicationKey] = options.ApplicationName; } if (options.ContentRootPath is not null){ (settings ??= new())[HostDefaults.ContentRootKey] = options.ContentRootPath; } if (options.WebRootPath is not null) { (settings ??= new())[WebHostDefaults.WebRootKey] = options.EnvironmentName; } if (settings != null) { config.AddInMemoryCollection(settings); } }); // 将BootstrapHostBuilder收集到配置和服务转移到Configuration和Services上 // 将应用到BootstrapHostBuilder上针对依赖注入容器的设置转移到_hostBuilder上 // 得到BuilderContext上下文 bootstrap.Apply(_hostBuilder, Configuration, Services, out var builderContext); // 如果提供了命令行参数,在Configuration上添加对应配置源 if (options.Args?.Any() == true) { Configuration.AddCommandLine(options.Args); } // 构建WebHostBuilderContext上下文 // 初始化Host、WebHost和Logging属性 var webHostContext = (WebHostBuilderContext)builderContext.Properties[typeof(WebHostBuilderContext)]; Environment = webHostContext.HostingEnvironment; Host = new ConfigureHostBuilder(builderContext, Configuration, Services); WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services); Logging = new LogginigBuilder(Services); } } ``` **简单来说 WebApplicationBuilder 的作用就是为了提供构建封装的一个 HostBuilder 对象** **注意:记住这 6 个属性,NetCore 的生态库基本上就是围绕这几个来构建的** 接下来我们按照这几个属性来逐一分析其作用 ##### **IWebHostEnvironment Environment 属性** 接口,继承 `IHostEnvironment`,提供一些该应用程序的环境信息,比如根目录、环境变量、名称等,包含几个属性 * `WebRootPath`,用于设置和获取 Web 的根目录,默认是 wwwroot 的子文件夹(在 5.0 的时候。是通过 Host.CreateDefaultBuilder()方法去设置的); * `ApplicationName:` 应用名称; * `ContentRootFileProvider:;` * `ContentRootPath:`; * `EnvironmentName:` 环境名称; 比如我们经常用的判断是否是开发环境就是用的该类 *demo* ```C# var builder = WebApplication.CreateBuilder(args); bool isDevelopment = builder.Environment.IsDevelopment(); ``` ##### IServiceCollection Services 属性 **依赖注入容器**,可以注入服务,也可也获取服务实例,继承于 `ICollection<ServiceDescriptor>泛型接口`,这个我们后续会在依赖注入章节详细描述。 通过往该属性添加系统服务支持,或者注入自己的服务 *demo* ```C# var builder = WebApplication.CreateBuilder(args); // 注入Sql数据库支持 builder.Services.AddDbContext<SqlDbContext>(); // 依赖注入 builder.Services.AddSingleton<PersonService>(); ``` ##### ConfigurationManager Configuration 属性 **配置管理,**是 6.0 版本新增的类,更见简单的用于获取和设置系统配置文件,替换掉了 5.0 版本中 `IConfigurationBuilder接口` 和 `IConfigurationRoot接口`(6.0 是把这 2 个接口整合在一起了,看源码可以发现 `ConfigureManager` 继承于这 2 个接口) *ConfigurationManager 密封类源码* ```C# public sealed class ConfigurationManager : IConfigurationBuilder, IConfigurationRoot, IConfiguration, IDisposable { public ConfigurationManager(); public string this[string key] { get; set; } public void Dispose(); public IEnumerable<IConfigurationSection> GetChildren(); public IConfigurationSection GetSection(string key); } public interface IConfigurationBuilder { IDictionary<string, object> Properties { get; } IList<IConfigurationSource> Sources { get; } IConfigurationBuilder Add(IConfigurationSource source); IConfigurationRoot Build(); } ``` **增加系统配置文件** 当你调用 `builder.Configuration.AddJsonFile("文件名称")拓展方法` 的来增加自定义配置文件的时候(实际上是往调用的 `IConfigurationBuilder.Add()` 方法往 `IList<IConfigurationSource> Sources { get; }属性` 增加了一条数据),会将立即加载提供程序并更新配置,这样可以不用等到 `Build()` 方法,可以避免在部分生成方法多次加载配置源数据。 *demo* ```C# var builder = WebApplication.CreateBuilder(args); builder.Configuration.AddJsonFile("servicesetting.json"); ``` **获取系统配置数据** *demo* ```C# var builder = WebApplication.CreateBuilder(args); ConfigurationManager config = builder.Configuration; string value1 = config["DBContextModel:SqlConnection"]; IConfigurationSection value2 = config.GetSection("DBContextModel"); ``` ##### ILoggingBuilder Logging 提供日志记录,包括控制台、调试、事件日志、TraceSource 等组件,你是不是在疑惑为什么创建项目的时候 appsetting.json 配置文件有一个这样的配置?他就和日志记录息息相关 *appstting.json 文件节点* ```json "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, ``` 具体在日志章节描述 ##### ConfigureWebHostBuilder WebHost 属性 继承于 `IWebHostBuilder接口`,目的是复用接口,继承于 `ISupportsStartUp接口`,由于 6.0 使用的是最小托管模型,所以传统的使用 `Startup.cs文件` 来配置服务和注册中间件已经不支持了,继承此接口的是原因是: > 微软原话“但是我们希望用户在采用这种编程方式时得到显式的提醒,所以依然让它实现该接口,并在实现的方法中抛出 NotImplementedException 类型的异常。” `WebApplication` 构造函数中,通过传进来的一些构造参数初始化一个实例赋值给该属性; 构造函数,通过 `WebHostContext,Services成员属性、Configure成员属性` 来初始化 *ConfigureWebHostBuilder 类源码* ```C# public class ConfigureWebHostBuilder : IWebHostBuilder, ISupportsStartup { private readonly WebHostBuilderContext _builderContext; private readonly IServiceCollection _services; private readonly ConfigurationManager _configuration; public ConfigureWebHostBuilder(WebHostBuilderContext builderContext, ConfigurationManager configuration, IServiceCollection services) { _builderContext = builderContext; _services = services; _configuration = configuration; } } ``` ##### ConfigureHostBuilder Host 属性 继承于 `IHostBuilder接口`,目的是复用接口,他更多的用来配置主机服务 `WebApplication构造函数` 中,通过 `bootStrapBuilder` 收集到的服务,传进来的一些构造参数初始化一个实例赋值给他; 构造函数,通过 `HostBuilderContext ,Services成员属性、Configure成员属性` 来初始化 * Services 成员属性会直接赋值 ConfigureHostBuilder 的\_services 属性 * Configure 成员属性相关 Host 的配置会被存放在 ConfigureHostBuilder 内部类的一个\_configureActions 字段暂时存起来 *ConfigureHostBuilder 类源码* ```C# public class ConfigureHostBuilder : IHostBuilder { private readonly ConfigurationManager _configuration; private readonly IServiceCollection _services; private readonly HostBuilderContext _context; private readonly List<Action<IHostBuilder>> _configureActions = new(); internal ConfigureHostBuilder(HostBuilderContext context, ConfigurationManager configuration, IServiceCollection services) { _configuration = configuration; _services = services; _context = context; } } ``` #### BootstrapHostBuilder 类:[#](https://www.cnblogs.com/boise/p/18002731#bootstraphostbuilder%E7%B1%BB) `BootstrapHostBuilder` 继承于 `IHostBuilder`,目的是为了构建和初始化 `IHostBuilder` 对象 这个它的作用是收集初始化 `IHostBuilder` 对象提供的设置并将它们分别应用到指定的 `IServiceCollection、ConfigurationManager和IHostBuilder对象` 上,在构造函数中会调用他的 `Apply()` 方法。 ## 2. Build()方法:[#](https://www.cnblogs.com/boise/p/18002731#2-build%E6%96%B9%E6%B3%95) 简单来说就是将对于 `WebApplicationBuilder` 的一切配置转移到 `IHostBuilder对象` 上,然后得到一个 `WebApplication对象` **注意!!!!!** `WebApplication` 一旦创建,环境变量、配置都不允许再次改变(虽然我们也用不着,但是知道就好) **这个方法作用:** 把 `WebApplication` 的 `Configure成员属性` 和 `Services成员属性` 转移到 `HostBuil` der 上面 *[WebApplication.Build()方法源码](https://github.com/dotnet/aspnetcore/blob/release/6.0/src/DefaultBuilder/src/WebApplicationBuilder.cs)* ```C# // 获取WebApplication对象,用于配置 HTTP 管道和路由的 Web 应用程序 public WebApplication Build() { // 在此处连接主机配置。我们不会尝试保留配置,在此处获取本身,因为我们不支持在创建构建器后更改主机值。 _hostBuilder.ConfigureHostConfiguration(builder => { builder.AddInMemoryCollection(_hostConfigurationValues); }); // 将ConfigurationManager的配置转移到_hostBuilder _hostBuilder.ConfigureAppConfiguration(builder => { builder.AddConfiguration(Configuration); foreach (var kv in ((IConfigurationBuilder)Configuration).Properties) { builder.Properties[kv.Key] = kv.Value; } }); var chainedConfigSource = new TrackingChainedConfigurationSource(Configuration); _hostBuilder.ConfigureServices((context, services) => { // 简单来说就是把WeApplicationBuilder中的IServiceCollection属性添加到泛型主机中 foreach (var s in _services) { services.Add(s); } // 把服务列表只能关于主机的服务添加到主机中 // 确保添加的任何托管服务在初始托管服务集之后运行。也就是托管服务在web主机启动前运行 foreach (var s in _services.HostedServices) { services.Add(s); } // 清除主机托管服务列表 _services.HostedServices.Clear(); // 将任何服务添加到用户可见的服务集合中, _services.InnerCollection = services; // 保留主机中的配置 var beforeChainedConfig = true; var hostBuilderProviders = ((IConfigurationRoot)context.Configuration).Providers; if (!hostBuilderProviders.Contains(chainedConfigSource.BuiltProvider)) { ((IConfigurationBuilder)Configuration).Sources.Clear(); beforeChainedConfig = false; } // 使配置管理器与最终_hostBuilder的配置匹配。 foreach (var provider in hostBuilderProviders) { if (ReferenceEquals(provider, chainedConfigSource.BuiltProvider)) { beforeChainedConfig = false; } else { IConfigurationBuilder configBuilder = beforeChainedConfig ? _hostConfigurationManager : Configuration; configBuilder.Add(new ConfigurationProviderSource(provider)); } } }); // 在最终主机构建器上运行其他回调 Host.RunDeferredCallbacks(_hostBuilder); // 构建应用 _builtApplication = new WebApplication(_hostBuilder.Build()); // 将服务集合标记为只读以防止将来修改 _services.IsReadOnly = true; // 解析_hostBuilder的配置和构建器。 _ = _builtApplication.Services.GetService<IEnumerable<IConfiguration>>(); return _builtApplication; } ``` ### WebApplication 类:[#](https://www.cnblogs.com/boise/p/18002731#webapplication%E7%B1%BB) 应用类 #### 继承 4 个接口[#](https://www.cnblogs.com/boise/p/18002731#%E7%BB%A7%E6%89%BF4%E4%B8%AA%E6%8E%A5%E5%8F%A3) * `IHost接口`:所以这就是上文当中说到为什么 `WebApplicationBuilder` 需要一个 `IConfigureHostBuilder` 属性的原因; * `IApplicationBuilder`:提供配置应用程序请求管道机制的类,所以我们的中间件可以直接注册到 `WebApplication`; * `IEndpointRouteBuilder`:定义应用程序中路由生成器的协定。 路由生成器指定应用程序的路由。所以我们无需显示调用 `UseEndpoint、UseRouting` 这 2 个中间件,这个在 6.0 的更新中也提到了; * `IAsyncDisposable`:提供异步释放的接口; #### 6 个重要属性[#](https://www.cnblogs.com/boise/p/18002731#6%E4%B8%AA%E9%87%8D%E8%A6%81%E5%B1%9E%E6%80%A7) * `IServiceProvider`:应用程序的已配置服务。提供在程序运行期间解析的服务类型,简称依赖注入容器; * `IConfiguration`:应用程序的已配置,可以获取已经配置好的配置源; * `IWebHostEnvironment`: 托管环境信息; * `IHostApplicationLifetime`:允许通知使用者应用程序生存期事件; * `ILogger`:日志服务; * `ICollection<string>` :HTTP 服务器绑定到的 URL 列表。(IServerAddressesFeature:启动地址); *WebApplication 类源码* ```c# public sealed class WebApplication : IHost, IApplicationBuilder, IEndpointRouteBuilder, IAsyncDisposable { public IServiceProvider Services => _host.Services; public IConfiguration Configuration => _host.Services.GetRequiredService<IConfiguration>(); public IWebHostEnvironment Environment => _host.Services.GetRequiredService<IWebHostEnvironment>(); public IHostApplicationLifetime Lifetime => _host.Services.GetRequiredService<IHostApplicationLifetime>(); public ILogger Logger { get; } public ICollection<string> Urls => ServerFeatures.Get<IServerAddressesFeature>()?.Addresses ?? throw new InvalidOperationException($"{nameof(IServerAddressesFeature)} could not be found."); } ``` #### 拓展方法[#](https://www.cnblogs.com/boise/p/18002731#%E6%8B%93%E5%B1%95%E6%96%B9%E6%B3%95) 就是各种系统定义好的中间件服务。 ## 3. Run()方法 :[#](https://www.cnblogs.com/boise/p/18002731#3-run%E6%96%B9%E6%B3%95-) ### WebApplication.BuildRequestDelegate()方法[#](https://www.cnblogs.com/boise/p/18002731#webapplicationbuildrequestdelegate%E6%96%B9%E6%B3%95) 前面调用 `ConfigureWebHostDefaults()` 扩展方法提供的委托会将使用 `BuildRequestDelegate()` 方法注册的中间件管道,作为请求处理器,至此一个 WebApplication 对象完成。 ```mipsasm ## 4. 总结 : 首先,最小托管模型是6.0微软推出来的一个新的应用模板,为的是方便配置和学习,他只有3句代码,利用他可以生成最小webapi。 第一句是var bulider = WebAppliaction.CreateBuilder(); 这句代码的作用是通过调用WebAppliaction的工厂方法CreateBuilder()得到WebApplicationBuilder对象,因为创建一个WebApplication对象需要一个Host,Host则必须由HostBuilder创建,所以WebApplicationBuilder对象的作用是提供一个封装好的HostBuilder对象用来构建IHost, 它含有6个属性以及一个构造函数,属性包括IServiceCollection依赖注入容器Services、ConfigureManage配置管理Configure、IWebHostEnvironment托管环境environment、ILoggingBuilder日志记录logging、ConfigureWebHostBuilder类型webhost、ConfigureHostBuilder类型host,需要这6个属性的目的就是用来提供HostBuilder的创建 构造函数的作用是根据传进来的命令行参数来初始化这些属性,首先他会初始化一个_hostBuilder对象,然后创建一个bootstrapBuilder对象用来调用他的拓展方法收集服务和配置,赋值给services和configure属性,接下里根据bootstrapBuilder对象的一些属性,初始化剩余属性,初始化WebHost和Host。 第二句代码是var app = bulider.bulider(); 在这句代码之前,我们可以注入自己的一些服务和系统服务,通过调用AddScope()等依赖注入方法或者使用系统提供的服务方法、如AddController(), 这句代码的作用是,根据得到WebApplicationBuilder对象来创建WebApplication,这句代码最重要的就是,把services和configure属性赋值给HostBuilder,然后我们可以看到这个对象继承了4个接口,一个是IHost接口,这就解释了为什么WebApplicationBuilder需要有一个ConfigurHostBuilder对象,还有一个IApplicationBuilder接口,这个接口是构建中间件管道服务的接口,所以我们的中间件可以直接注册在WebApplication的原因,IEndpointRouteBuilder则是默认构造了路由,还有一个异步释放的接口。 第三句代码是app.Run(); 在这句代码之前可以注入中间件服务,比如UseAuthorization()之类的, 这句代码的作用是,通过调用WebApplication内部的BuildRequestDelegation()方法把注册的中间件管道作为请求处理器,至此一个WebApplication对象完成 所以根据这几行代码我们不难看出,WebApplication其实就是对Host的再次封装,只是为了我们更加简单的去配置一些我们需要的服务和中间件 ```
个人天使
2025年2月10日 13:55
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码