ASP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline)。日志记录、用户认证、MVC等模块都以中间件(Middleware)的方式注册在管道中。显而易见这样的设计非常松耦合并且非常灵活,你可以自己定义任意功能的Middleware注册在管道中。这一设计非常适用于“请求-响应”这样的场景——消息从管道头流入最后反向流出。

在本文中暂且为这种模式起名叫做“管道-中间件(Pipeline-Middleware)”模式吧。

本文将描述”管道-中间件模式”的“契约式”设计和“函数式”设计两种方案。

一、什么是管道-中间件模式?

在此模式中抽象了一个类似管道的概念,所有的组件均以中间件的方式注册在此管道中,当请求进入管道后:中间件依次对请求作出处理,然后从最后一个中间件开始处理响应内容,最终反向流出管道。

二、契约式设计

契约式设计是从面向对象的角度来思考问题,根据管道-中间件的理解,中间件(Middleware)有两个职责:

1
2
3
4
5
public  interface  IMiddleware
{
     Request ProcessRequest(Request request);
     Response ProcessResponse(Response response);
}

管道(Pipeline)抽象应该能够注册中间件(Middleware):

1
2
3
4
5
6
7
8
9
public  interface  IApplicationBuilder
{
     void  Use(IMiddleware middleware);
     void  UseArrange(List<IMiddleware> middlewares);
     Context Run(Context context);
}

实现IApplicationBuilder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
3 2
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public  class  ApplicationBuilder : IApplicationBuilder
{
     public  IWindsorContainer Container { get ; private  set ; }
     private  readonly  List<IMiddleware> _middlewares;
     public  ApplicationBuilder(IWindsorContainer container)
     {
         Contract.Requires(container!= null , "container!=null" );
         _middlewares= new  List<IMiddleware>();
         Container = container;
     }
     public  void  Use(IMiddleware middleware)
     {
         Contract.Requires(middleware != null , "middleware!=null" );
         _middlewares.Add(middleware);
     }
     public  void  UseArrange(List<IMiddleware> middlewares)
     {
         Contract.Requires(middlewares != null , "middlewares!=null" );
         _middlewares.AddRange(middlewares);
     }
     public  Context Run(Context context)
     {
         Contract.Requires(context!= null , "context!=null" );
         var  request=context.Request;
         var  response=context.Response;
         foreach  ( var  middleware in  _middlewares)
         {
             request = middleware.ProcessRequest(request);
         }
         _middlewares.Reverse();
         foreach  ( var  middleware in  _middlewares)
         {
             response = middleware.ProcessResponse(response);
         }
         return  new  Context(request,response);
     }
}

Run()方法将依次枚举Middleware并对消息的请求和响应进行处理,最后返回最终处理过的消息。

接下来需要实现一个Middleware:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public  class  DefaultMiddleware:IMiddleware
  {
      public  Request ProcessRequest(Request request)
      {
          request.Process( "default request" , "processed by defaultMiddleware" );
          return  request;
      }
      public  Response ProcessResponse(Response response)
      {
          response.Process( "default response" , "processed by defaultMiddleware" );
          return  response;
      }
  }

为了将Middleware注册进管道,我们还可以写一个扩展方法增加代码的可读性:

1
2
3
4
5
6
7
8
9
10
11
12
public  static  void  UseDefaultMiddleware( this  IApplicationBuilder applicationBuilder)
{
     applicationBuilder.Use<DefaultMiddleware>();
}
public  static  void  Use<TMiddleware>( this  IApplicationBuilder applicationBuilder)
     where  TMiddleware:IMiddleware
{
     var  middleware = applicationBuilder.Container.Resolve<TMiddleware>();
     applicationBuilder.Use(middleware);
}

写个测试看看吧:

写第二个Middleware:

1
2
3
4
5
6
7
8
9
10
11
12
13
1 15
16
public  class  GreetingMiddleware:IMiddleware
{
     public  Request ProcessRequest(Request request)
     {
         request.Process( "hello, request" , "processed by greetingMiddleware" );
         return  request;
     }
     public  Response ProcessResponse(Response response)
     {
         response.Process( "hello, request" , "processed by greetingMiddleware" );
         return  response;
     }
}

编写测试:

三、函数式设计方案

此方案也是Owin和ASP.NET Core采用的方案,如果站在面向对象的角度,第一个方案是非常清晰的,管道最终通过枚举所有Middleware来依次处理请求。

站在函数式的角度来看,Middleware可以用Func<Context, Context>来表示,再来看看这张图:

一个Middleware的逻辑可以用Func<Func<Context, Context>, Func<Context, Context>>来表示,整个Middleware的逻辑可以用下面的代码描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public  Func<Func<Context, Context>, Func<Context, Context>> Process()
{
     Func<Func<Context, Context>, Func<Context, Context>> middleware = next =>
     {
         Func<Context, Context> process = context =>
         {
             /*process request*/
           
             next(context);
             /*process response*/
             return  context;
         };
         return  process;
     };
     return  middleware;
}

这一过程是理解函数式方案的关键,所有Middleware可以聚合为一个Func<Context,Context>,为了易于阅读,我们可以定义一个委托:

1
public  delegate  Context RequestDelegate(Context context);

给定初始RequestDelegate,聚合所有Middleware:

1
2
3
4
5
6
7
8
9
10
11
1 13
public  IApplication Build()
{
     RequestDelegate request = context => context;
     _middlewares.Reverse();
     foreach  ( var  middleware in  _middlewares)
     {
         request = middleware(request);
     }
     return  new  Application(request);
}

自定义一个函数式Middleware:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1 8
19
20
21
22
public  class  DefaultMiddleware:IMiddleware
{
     public  Func<RequestDelegate, RequestDelegate> Request()
     {
         Func<RequestDelegate, RequestDelegate> request = next =>
         {
             return  context =>
             {
                 context.Request.Process( "default request" , "processed by defaultMiddleware" );
                 next(context);
                 context.Response.Process( "default response" , "processed by defaultMiddleware" );
                 return  context;
             };
         };
         return  request;
     }
}

所有代码提供下载:https://git.oschina.net/richieyangs/Pipeline.Middleware.git

相关文章

  • ASP.NET Core 1.0 入门——Application Startup

  • ASP.NET Core 1.0 入门——了解一个空项目

  • ASP.NET Core 1.0 部署 HTTPS (.NET Framework 4.5.1)

  • .NET Core 1.0、ASP.NET Core 1.0和EF Core 1.0简介

  • 云服务器下ASP.NET Core 1.0环境搭建(包含mono与coreclr)

  • 使用VS Code开发ASP.NET Core 应用程序

  • dotnet run是如何启动asp.net core站点的

  • ASP.NET Core提供模块化Middleware组件

  • “dotnet restore"和"dotnet run"都做了些什么?

  • 探秘 dotnet run 如何运行 .NET Core 应用程序

  • .NET Portability Analyzer 已开源

  • .NET跨平台之旅:corehost 是如何加载 coreclr 的

  • ASP.NET Core 行军记 -----拔营启程

  • 如何迁移#SNMP到.NET Core平台的一些体会

原文地址:http://www.cnblogs.com/richieyang/p/5315390.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

ASP.NET Core 1.0中的管道-中间件模式相关推荐

  1. ASP.NET Core 2.0 : 八.图说管道,唐僧扫塔的故事

    ASP.NET Core 2.0 : 八.图说管道,唐僧扫塔的故事 原文:ASP.NET Core 2.0 : 八.图说管道,唐僧扫塔的故事 本文通过一张GIF动图来继续聊一下ASP.NET Core ...

  2. ASP.NET Core 3.0中使用动态控制器路由

    原文:Dynamic controller routing in ASP.NET Core 3.0 作者:Filip W 译文:https://www.cnblogs.com/lwqlun/p/114 ...

  3. 避免在 ASP.NET Core 3.0 中为启动类注入服务

    本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇. Part 1 - 将.NET Standard 2.0 类库转换为.NET Core 3.0 类库 Part 2 - IHostin ...

  4. asp.net core 3.0 中使用 swagger

    asp.net core 3.0 中使用 swagger Intro 上次更新了 asp.net core 3.0 简单的记录了一下 swagger 的使用,那个项目的 api 比较简单,都是匿名接口 ...

  5. ASP.Net Core 2.0中的Razor Page不是WebForm

    随着.net core2.0的发布,我们可以创建2.0的web应用了.2.0中新东西的出现,会让我们忘记老的东西,他就是Razor Page.下面的这篇博客将会介绍ASP.Net Core 2.0中的 ...

  6. 在ASP.NET Core 2.0中使用CookieAuthentication

    在ASP.NET Core中关于Security有两个容易混淆的概念一个是Authentication(认证),一个是Authorization(授权).而前者是确定用户是谁的过程,后者是围绕着他们允 ...

  7. 在ASP.NET Core 2.0中创建Web API

    目录 介绍 先决条件 软件 技能 使用代码 第01步 - 创建项目 第02步 - 安装Nuget包 步骤03 - 添加模型 步骤04 - 添加控制器 步骤05 - 设置依赖注入 步骤06 - 运行We ...

  8. ASP.NET Core 3.0中支持AI的生物识别安全

    本文共两个部分,这是第一部分,其中介绍了 ASP.NET Core 3 中旨在将授权逻辑与基本的用户角色相分离的基于策略的授权模型. 此部分提供了此授权进程的基于生物识别信息(如人脸识别或语音识别)的 ...

  9. 在ASP.NET Core 2.0中使用MemoryCache

    说到内存缓存大家可能立马想到了HttpRuntime.Cache,它位于System.Web命名空间下,但是在ASP.NET Core中System.Web已经不复存在.今儿个就简单的聊聊如何在ASP ...

最新文章

  1. React 组件之间传递参数
  2. python mysql 编码方式,Python3编码与mysql编码介绍
  3. linux中用户的分类
  4. 【已解决】github中git push origin master出错:error: failed to push some refs to(亲测)
  5. Hystrix Health Indicator及Metrics Stream支持
  6. (转)zabbix3.4使用percona-monitoring-plugins监控mysql
  7. php 类的属性与方法的注意事项
  8. myeclipse背景设置
  9. Bootstrap条纹进度条
  10. 华为取代苹果 手机销量再创新高
  11. Sonarqube plugin插件 在使用Sonar-scanner时不能 扫描 file index 动态新生成的文件 解决方案
  12. 干货!!月薪过万行业,软件测试必懂的基本概念
  13. 签到新旧版本更替问题
  14. 给一张表加一个自动编号字段_Python办公自动化|从Word到Excel
  15. java模板引擎哪个好_Java 常用模板引擎推荐
  16. 收银系统服务器ip设置,如何修改打印机IP地址?
  17. movielens电影数据分析
  18. Horspool算法
  19. 如果面试遇到临时面试官,怎么办?
  20. 解决URP资源的材质成洋红色问题

热门文章

  1. 【CSS基础】实现 div 里的内容垂直水平居中
  2. 第十一周项目3-程序的多文件组织
  3. Imageready(IR)动画介绍
  4. QOMO Linux 4.0 正式版发布
  5. .NET 生态系统的蜕变之 .NET 6云原生
  6. C# 修改配置文件进行窗体logo切换
  7. Web服务器HttpServer(嵌入式设备)
  8. 微软面向初学者的机器学习课程:3.1-构建使用ML模型的Web应用程序
  9. OceanBase开源,11张图带你了解分布式数据库的核心知识
  10. NET问答: 如何避免在 EmptyEnumerable 上执行 Max() 抛出的异常 ?