.NET 8 IApplicationBuilder详解
在上节中我们已经得知 WebApplication 实现了 IApplicationBuilder,我们浅谈了其pipe特质和构建方法,本节中将深入了解 ApplicationBuilder 以窥探 IApplicationBuilder 真相
public interface IApplicationBuilder
{
IServiceProvider ApplicationServices { get; set; }
IFeatureCollection ServerFeatures { get; }
IDictionary<string, object?> Properties { get; }
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
IApplicationBuilder New();
RequestDelegate Build();
}
管道机制
该机制是.NET最关键的机制之一,贯彻整个APP生命周期,但他的实现,简单巧妙的让人惊叹。
首先在内部维护了一个 Func<RequestDelegate, RequestDelegate> 集合
private readonly List<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>();
Func<RequestDelegate, RequestDelegate> 还有一个美腻的别名叫:中间件,UseMiddleware 的本质,就是 IApplicationBuilder.Use,调用 Use 其实就是添加一个中间件到集合
public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
{
this._components.Add(middleware);
return (IApplicationBuilder) this;
}
最终在 Build 生成此应用程序用于处理HTTP请求的委托。
public RequestDelegate Build()
{
RequestDelegate requestDelegate = (RequestDelegate) (context =>
{
Endpoint endpoint = context.GetEndpoint();
if (endpoint?.RequestDelegate != null)
throw new InvalidOperationException("The request reached the end of the pipeline without executing the endpoint: '" + endpoint.DisplayName + "'. Please register the EndpointMiddleware using 'IApplicationBuilder.UseEndpoints(...)' if using routing.");
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
for (int index = this._components.Count - 1; index >= 0; --index)
requestDelegate = this._components[index](requestDelegate);
return requestDelegate;
}
为什么要倒着循环呢?这是因为在ASP.NET Core中,中间件的执行顺序是按照它们在ApplicationBuilder中注册的顺序来决定的。后注册的中间件会在前注册的中间件之前执行,这就是经典的洋葱模型

Properties&Features
Properties 是一个字典,用于在中间件之间共享数据。
public IDictionary<string, object?> Properties { get; }
为了防止在中间件中修改 ApplicationBuilder 对象的状态,实现了一个原型模型:仅复制 Properties
public IApplicationBuilder New() => (IApplicationBuilder) new ApplicationBuilder(this);
private ApplicationBuilder(ApplicationBuilder builder) => this.Properties = (IDictionary<string, object>) new CopyOnWriteDictionary<string, object>(builder.Properties, (IEqualityComparer<string>) StringComparer.Ordinal);
Features 用于获取应用程序Server提供的一组HTTP features,如果程序没有指定Server,则返回空集合
public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>, IEnumerable
在 ApplicationBuilder 中 Features 直接引用 Properties,他们两者基本等价。而在 WebApplication 中,通过 IServer 提供
IFeatureCollection ServerFeatures => this._host.Services.GetRequiredService<IServer>().Features;
IServer是服务器知识,看同学们述求,考虑是否讲
IServiceProvider
IServiceProvider 用于访问应用程序服务容器,位于 System 命名空间,在整个 .NET 中举重若轻。它的功能非常简洁,只做一件事情,仅有一个方法,用于从服务容器中获取给定服务的实现。
public interface IServiceProvider
{
/// <summary>Gets the service object of the specified type.</summary>
/// <param name="serviceType">An object that specifies the type of service object to get.</param>
/// <returns>A service object of type <paramref name="serviceType" />.
/// -or-
/// <see langword="null" /> if there is no service object of type <paramref name="serviceType" />.</returns>
object? GetService(Type serviceType);
}
服务容器化,横空出世;依赖注入,孕育而生

浙公网安备 33010602011771号