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

  • 相关阅读:
    HTML简介
    【JAVA】【基础语法】Java中条件表达式的参数类型转换
    【JAVA】【基础语法】Java中操作运算符的细节
    【JAVA】【基础类型】StringBuffer和StringBuilder
    【JAVA】【基础类型】String类型的字符串池
    【JAVA】【基础类型】Java中封装类-String封装类
    【JAVA】【基础类型】Integer类型的常量池
    【JAVA】【基础类型】Java中的不可变类型
    【JAVA】【基础类型】Java中封装类-Math数学运算类
    【JAVA】【基础类型】Java中封装类-封装类型和基础类型
  • 原文地址:https://www.cnblogs.com/menglin2010/p/13072498.html
Copyright © 2011-2022 走看看