zoukankan      html  css  js  c++  java
  • 4.5管道实现机制和模拟构建管道「深入浅出ASP.NET Core系列」

    希望给你3-5分钟的碎片化学习,可能是坐地铁、等公交,积少成多,水滴石穿,谢谢关注。

    管道实现机制

    要了解管道的实现机制,我们必须要深入框架的源码,幸亏微软开源了,我们可以访问GitHub的地址来下载源码。

    git clone后,我们打开工程,进入Microsoft.AspNetCore.Http项目搜索ApplicationBuilder类(如下图),RequestDelegate是中间件的核心,而ApplicationBuilder是接收多个RequestDelegate的集合,所以解析ApplicationBuilder是了解整个管道实现的重要内容。而ApplicationBuilder里有两个重要的方法Build和Use也是我们关注的焦点。

       

    Use方法

      

      我们看下Use方法的参数是一个委托,该委托接收一个RequestDelegate参数,返回一个RequestDelegate,而_components.Add(middleware);是什么呢?我们看下这个全局变量的定义:

      

       _components就是一个IList列表容器,也就是说Use方法做的事情非常简单,就是不断的把中间件middleware往容器里面加而已,而中间件是什么?就是一个由RequestDelegate构成的委托罢了。   

      我们知道Use还有一个重载方法,他是一个扩展方法,可以在UseExtensions找到(如下图),这个扩展方法其实也是调用上面的Use方法,往容器添加内容。

      

      包括Run方法和上面类似,都是往容器灌入Middleware中间件。

      

    Build方法

       Use完了之后,接下来做什么呢?我们看下Build实现代码。

      

      这里对RequestDelegate集合进行反转,然后逐一调用执行,所以app会被最后一个执行。最后只返回一个RequestDelegate 

    模拟构建管道

       接下来,我们来模拟管道的构建过程,我们先建两个类,一个是RequestDelegate.cs和HttpContext.cs。

      

      HttpContext.cs我们假设没有任何实现:

      

      RequestDelegate.cs定义一个委托

      

      因为是模拟,所以我们这里使用控制台来测试,dotnet new console --name iConsole

      我们在Program.cs实现核心代码如下:

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    
    namespace iConsole
    {
        class Program
        {
            private static readonly IList<Func<RequestDelegate, RequestDelegate>> _mycomponents = 
                new List<Func<RequestDelegate, RequestDelegate>>();
    
            static void Main(string[] args)
            {
                //以下是Lambada表达式的简写
                Use(next =>
                {
                    return context =>
                    {
                        Console.WriteLine("PipeLine 1……");
                        return next.Invoke(context);
                    };
                });
    
                Use(next =>
                {
                    return context =>
                    {
                        Console.WriteLine("PipeLine 2……");
                        return next.Invoke(context);
                    };
                });
    
                RequestDelegate PipeLine_end = context =>
                {
                    Console.WriteLine("PipeLine_end……");
                    return Task.CompletedTask;
                };
    
                foreach (var component in _mycomponents)
                {
                    PipeLine_end = component(PipeLine_end);
                }
    
                PipeLine_end.Invoke(new HttpContext());
    
                Console.ReadLine();
            }
    
            public static void Use(Func<RequestDelegate,RequestDelegate> middleware)
            {
                _mycomponents.Add(middleware);
            }
        }
    }

      dotnet run后效果如下,整个模拟过程结束,是不是很简单呢。

      

      以上代码大部分是截图,截图看起来更加顺眼,虽然不方便复制,如果你想看完整代码可以访问我的GitHub地址

      希望以上分享对你有帮助,我是IT人张飞洪,入行10年有余,人不堪其忧,吾不改其乐,谢谢您关注

  • 相关阅读:
    六、springboot集成Swagger2
    五、springboot单元测试
    四、Springboot Debug调试
    三、springboot热部署
    二、springboot配置
    一、springboot入门
    SpringBoot整合RabbitMQ
    消息总线
    分布式配置
    路由网关---zuul
  • 原文地址:https://www.cnblogs.com/jackyfei/p/9956347.html
Copyright © 2011-2022 走看看