AspNetCore 中间件 ---- 委托

什么是中间件

Asp.Net中间件指的是一个独立的应用程序,它是asp.net应用程序处理Http请求管道的一个组成部分。中间件可以对游走在其中的Http请求或者响应做出修改,例如一个身份验证的中间件就可以从Http请求中读取信息并和数据库中的信息做匹配,根据匹配结果显示对应的http的响应结果。

 

RequestDelegate

asp.net中间件是http处理管道的一部分,所以中间件的主要作用就是处理当前http请求。asp.net中,当前http请求的所有信息都被封装到HttpContext对象中,可以由该对象来控制http请求的请求和响应。这样,我们就可以把中间件抽象为一种操作,这个操作接收一个HttpContext对象,并对他进行一些处理。所以很容易我们就能想到把这个操作定义为一个函数:

public void Middleware(HttpContext context);

每个中间件处理函数的名字可能不尽相同,但是有一点共同的就是他们都接受一个HttpContext对象。在OOP中,类是对对象的抽象,而在C#中,委托则是对函数的抽象。这样我们就容易的将上面这个函数抽象为一个委托:

public delegate void Middleware(HttpContext context);

RequestDelegate就是这样一个委托,唯一不同的是,他返回的是一个Task类型:

public delegate Task RequestDelegate(HttpContext context);

但是AspNetCore中的中间件定义是:

public Func<RequestDelegate, RequestDelegate> Middleware;

 

Func<RequestDelegate, RequestDelegate>

为什么不是RequestDelegate?因为aspnetcore中,管道就是中间件串联成的一条链,Http请求在通过这个管道时,会有不同的中间件对他处理,并把处理结果返回给下一个中间件。所以我们很容易想到Func第一个参数是上一个中间件的处理结果,第二个就是当前中间件的处理结果。但是~~~~,事情并没有这么简单,第一个RequestDelegate代表的是下一个中间件

为什么第一个RequestDelegate是下一个中间件呢?就如上面所说,aspnet core的http请求处理管道就是由中间件串联的管道,所以对于管道中下一个中间件的调用,就交给上一个中间件负责。如果上一个中间件决定不调用下一个中间件,那整个管道末端就是上一个中间件,也就是所谓的短路(short-circuiting)。

下面来看一下具体的代码实现。

ApplicationBuilder

首先对于ApplicationBuilder对象来说,它有一个存储中间件的列表对象_components:

private readonly IList<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>();

 

当我们每次调用 app.Use(Func<RequestDelegate, RequestDelegate> middleware) 方法时,就会将中间件添加到这个列表中:

public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
{
    _components.Add(middleware);
    return this;
}

 

当调用app.Build()方法时,会逆序遍历这个中间件列表,并且将当前middleware包装成RequestDelegate的形式,传递给前一个middleware,由它决定是否要调用当前中间件。值得注意的是,Build方法里,默认在整个管道末端添加了一个返回404的中间件,所以如果不添加任何中间件,最后response返回的就是404(还没试验过)。源代码如下:

public RequestDelegate Build()
{
    RequestDelegate app = context =>
    {
        context.Response.StatusCode = 404;
        return Task.FromResult(0);
    };

    foreach (var component in _components.Reverse())
    {
        app = component(app);
    }

    return app;
}

比如我们有三个中间件A, B, C,在StartUp.cs的Configure中依次添加这三个中间件。那么其实整个管道总共由4个中间件构成,依次是:A, B, C, 404,在我们调用Build()方法时,先创建一个404中间件的委托,然后将他作为next传给C,C再把自身作为next传给B,依此类推,最后返回的app就是A,此时A中已经有了B中间件的委托,可以选择自行选择调用B或者直接短路。

欢迎指正错误。

下一篇我们会详细介绍一下中间件的用法以及中间件包装的过程。

转载于:https://www.cnblogs.com/joe06102/p/6987002.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值