zoukankan      html  css  js  c++  java
  • ASP.NET Core 3.1--中间件源码解读--RequestDelegate--ApplicationBuilder.Use

    一、RequestDelegate的定义
    从RequestDelegate定义可以看出,RequestDelegate是接收请求上下文HttpContext的一个委托,RequestDelegate既然是一个委托,委托就是一个方法,所以RequestDelegate就是个方法,是个接受请求上下文的方法。

    public delegate Task RequestDelegate(HttpContext context);

    二、 IApplicationBuilder.Use的定义
    我们对比来看,下面这个func是接收1个int 类型的参数,返回1个string类型的委托

    Func<int, string> func = new Func<int, string>(i => 
    {
        return "abc";
    });
    string result = func(123);

    在看ApplicationBuilder.Use()的定义
    ApplicationBuilder.Use方法接收1个Func委托,这个Func接收1个RequestDelegate类型的参数,返回1个RequestDelegate类型,上面说了RequestDelegate是个方法,那么也就是说ApplicationBuilder.Use方法接收1个方法,返回1个方法。

    IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);

    三、ApplicationBuilder.Use需要的参数的简写
    这时候requestdelegate是个方法,但是是什么方法,我们还不知道,我们往下看

    //1、Func委托,这个Func接收1个RequestDelegate类型的参数,返回1个RequestDelegate类型
    Func<RequestDelegate, RequestDelegate> func = new Func<RequestDelegate, RequestDelegate>((RequestDelegate requestdelegate) =>
    {
        return new RequestDelegate(async (context) =>
        {
            await context.Response.WriteAsync("接收1个带RequestDelegate类型的参数,返回RequestDelegate类型的委托");
        });
    });
    
    //2、简写这个委托
    Func<RequestDelegate, RequestDelegate> func = (requestdelegate =>
    {
        return new RequestDelegate(async (context) =>
        {
            await context.Response.WriteAsync("简写func委托!");
        });
    });
    
    //3、Use中间件,最终简写
    app.Use(requestdelegate =>
    {
        return new RequestDelegate(async (context) =>
        {
            await context.Response.WriteAsync("Use中间件!");
        });
    });

    四、看源码解读中间件注册和执行流程
    为什么输出顺序是This is Middleware 3--->This is Middleware 2--->This is Middleware 1
    为什么输出顺序是This is Hello World 1 Start--->This is Hello World 2 Start--->This is Hello World 3 Start--->This is Hello World 3 End--->This is Hello World 2 End--->This is Hello World 1 End

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
    { 
        app.Use(next =>
        {
            Console.WriteLine("This is Middleware 1");
            return new RequestDelegate(
                async context =>
                {
                    await context.Response.WriteAsync("This is Hello World 1 Start");
                    await next.Invoke(context);
                    await context.Response.WriteAsync("This is Hello World 1 End");
                });
        });
        app.Use(next =>
        {
            Console.WriteLine("This is Middleware 2");
            return new RequestDelegate(
                async context =>
                {
                    await context.Response.WriteAsync("This is Hello World 2 Start");
                    await next.Invoke(context);
                    await context.Response.WriteAsync("This is Hello World 2 End");
                });
        });
        app.Use(next =>
        {
            Console.WriteLine("This is Middleware 3");
            return new RequestDelegate(
                async context =>
                {
                    await context.Response.WriteAsync("This is Hello World 3 Start");
                    await context.Response.WriteAsync("This is Hello World 3 End");
                });
        });  
    }

    1、ApplicationBuilder.Use方法源码解读
    从源码看出ApplicationBuilder.Use方法就是把Func<RequestDelegate, RequestDelegate> middleware添加到_components这个集合里,而从_components的定义看出_components是个委托集合。

     

    2、中间件执行源码解读
    从源码看出有个默认的RequestDelegate app,把委托集合反转,遍历执行。
    所以先输出This is Middleware 3,后输出This is Middleware 2,最后输出This is Middleware 1,最终返回的是第1个中间件。

    第3个中间件的传入参数是默认的RequestDelegate app
    第2个中间件的传入参数是第3个中间件的返回值
    第1个中间件的传入参数是第2个中间件的返回值

    第3个中间件的next是默认的RequestDelegate app
    第2个中间件的next是第3个中间件的返回值
    第1个中间件的next是第2个中间件的返回值
    所以最后的输出顺序是This is Hello World 1 Start--->This is Hello World 2 Start--->This is Hello World 3 Start--->This is Hello World 3 End--->This is Hello World 2 End--->This is Hello World 1 End

  • 相关阅读:
    SQLite在php中的接口
    Smarty3——内置函数
    Smarty3——foreach
    Smarty3——复合变量修饰器输
    Smarty3——从配置文件获取的变量
    Smarty3——变量修饰器
    Git命令
    容器云----docker-registry+docker-registry-web(镜像仓库+镜像仓库管理界面)
    容器云----kubernetes-dashboard(kubernetes管理界面)
    容器云----kubernetes+docker-ce
  • 原文地址:https://www.cnblogs.com/menglin2010/p/13072498.html
Copyright © 2011-2022 走看看