这批.Net程序员水平不行啊!居然ASP.NET Core Middleware都不会用

最近问了几个面试同一个问题:如果有多个自定义Middleware,如何控制它们的执行顺序(比如先判断用户合法再写访问日志)。居然大部分人答不上来?! 

对此,你有什么看法?

ASP.NET Core Middleware的调用顺序

这里我直接贴上官方文档[1]中的图片: 

ASP.NET Core 请求管道包含一系列请求委托,依次调用。而调用顺序实际上就是我们在Startup.cs中注册(使用UseMiddlewareExtensions.UseMiddleware方法)它们的顺序。

示例代码如下:

public void ConfigureServices(IServiceCollection services)
{//注册生命周期services.AddTransient<TransientMiddleware>();services.AddScoped<ScopedMiddleware>();
}public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{//注册调用顺序app.UseMiddleware<TransientMiddleware>();app.UseMiddleware<ScopedMiddleware>();
}

但这种方式,对于调整自定义Middleware的需求,需要经常修改Startup.cs,而且会使代码比较凌乱,可读性较差。

可以使用下面的方式,简化注册代码:

public void ConfigureServices(IServiceCollection services)
{services.AddMiddlewares();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseMiddlewares();
}

实现方式

1.定义Attribute

MiddlewareRegisterAttribute将放在每个Middleware实现类上,表明它是需要被注册的Middleware。

[AttributeUsage(AttributeTargets.Class)]
public class MiddlewareRegisterAttribute : Attribute
{//注册顺序public int Sort { get; set; } = int.MaxValue;//生命周期public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Scoped;
}

2.定义注册信息类

MiddlewareRegisterInfo用于存放Middleware的注册信息,供注册方法调用。

public class MiddlewareRegisterInfo
{public MiddlewareRegisterInfo(Type type,MiddlewareRegisterAttribute attribute){Type = type;Sort = attribute.Sort;Lifetime = attribute.Lifetime;}public Type Type { get; private set; }public int Sort { get; private set; }public ServiceLifetime Lifetime { get; private set; }
}

2.实现注册扩展方法

读取Assembly中的Type, 如果存在MiddlewareRegisterAttribute就把它放入List<MiddlewareRegisterInfo>列表中,最后根据Sort属性顺序依次注册,代码如下:

public static class MiddlewareRegisterExtensions
{private static readonly IEnumerable<MiddlewareRegisterInfo> _middlewareRegisterInfos = GetMiddlewareRegisterInfos();public static IServiceCollection AddMiddlewares(this IServiceCollection services){foreach (var middlewareRegisterInfo in _middlewareRegisterInfos){switch (middlewareRegisterInfo.Lifetime){case ServiceLifetime.Singleton:services.AddSingleton(middlewareRegisterInfo.Type);break;case ServiceLifetime.Transient:services.AddTransient(middlewareRegisterInfo.Type);break;default:services.AddScoped(middlewareRegisterInfo.Type);break;}}return services;}public static IApplicationBuilder UseMiddlewares(this IApplicationBuilder applicationBuilder){foreach (var middlewareRegisterInfo in _middlewareRegisterInfos){applicationBuilder.UseMiddleware(middlewareRegisterInfo.Type);}return applicationBuilder;}private static List<MiddlewareRegisterInfo> GetMiddlewareRegisterInfos(){var middlewareRegisterInfos = new List<MiddlewareRegisterInfo>();//所有包含Middleware的Assemblyvar assemblies = new Assembly[] { typeof(Startup).Assembly };foreach (var assembly in assemblies){foreach (var type in assembly.GetTypes().Where(x => !x.IsAbstract)){var attribute = type.GetCustomAttribute<MiddlewareRegisterAttribute>();if (attribute != null){middlewareRegisterInfos.Add(new MiddlewareRegisterInfo(type, attribute));}}}return middlewareRegisterInfos.OrderBy(p=>p.Sort).ToList();}
}

测试一下

创建3个Middleware,功能仅仅是输出日志:

[MiddlewareRegister(Sort = 100)]
public class OneMiddleware : IMiddleware
{private readonly ILogger<OneMiddleware> logger;public OneMiddleware(ILogger<OneMiddleware> logger){this.logger = logger;}public async Task InvokeAsync(HttpContext context, RequestDelegate next){logger.LogInformation("One");await next(context);}
}

Sort用100、200、300,方便后面修改排序。

运行效果如下图:

现在,将ThreeMiddleware的Sort改为150,调整注册顺序,再次运行,效果如下图: 

结论

当然,这个解决方案也存在一些缺点,比如修改排序的位置移到每个Middleware,比较分散。但整体来说,代码更易读

如果你有其他实现方式,欢迎到公众号后台留言指教。

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!

参考资料

[1]

官方文档: https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/300488.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Heroku上部署(托管)Rails项目

2019独角兽企业重金招聘Python工程师标准>>> ①、安装heroku&#xff1a; &#xff04; gem install heroku ②、先要生成一个公钥&#xff0c;使用命令: $ ssh-keygen -t rsaGenerating public/private rsa key pair. Enter file in which to save the key (/home/…

企业流程管理平台V2.0介绍

一个软件产品的核心价值在于它适应变化的能力&#xff0c;软件业在中国发展的二十年的历程里&#xff0c;您也许选择过也痛苦过&#xff1b;软件本身并不具有任何直接的价值&#xff0c;但它能为您的企业带来信息的价值、效率的价值及降低成本的价值&#xff0c;然而&#xff0…

java关于异常的面试程序题_Java挑战:最难的十个面试题(附答案)「下」

原标题&#xff1a;Java挑战&#xff1a;最难的十个面试题(附答案)「下」版权声明&#xff1a;本文为CSDN博主「华为云」的原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接及本声明。原文链接&#xff1a;https://blog.csdn.net/devcloud/a…

数学知识点大集合!有了它学数学真的很简单!

▲ 点击查看很多学生对于数学这门学科都有莫名的恐惧感&#xff0c;不知道怎样学才能学得好。其实&#xff0c;好的方法能让学习效率达到最佳效果。有的时候&#xff0c;孩子学习不好&#xff0c;真的不是因为孩子笨&#xff0c;而是这种方法不适合孩子。其实小学数学学习的难度…

WinAPI: waveOutGetNumDevs - 获取波形输出设备的数目

//声明: waveOutGetNumDevs: UINT; {无参数; 返回波形输出设备的数目}//举例:转载于:https://www.cnblogs.com/del/archive/2008/02/20/1075521.html

使用 Blazor 开发内部后台(三):登录

James: 《使用Blazor开发内部后台》系列是技术社区中一位朋友投稿的系列文章&#xff0c;介绍自己为公司的 WebForm 遗留系统使用 Blazor 重写前端 UI 的经历。本文为第三篇&#xff0c;如果错过了前两篇&#xff0c;建议先阅读一下&#xff1a;使用 Blazor 开发内部后台&#…

PHP访问连接MYSQL数据库

1.连接数据库 使用mysql_connect()函数建立与MySQL数据库的连接 源码&#xff1a;$conmysql_connect(“主机名或IP”,”用户名”,”密码”) or die(“不能连接到数据库&#xff0c;可能是数据库服务器为启动或用户名密码错误”.mysql_error()); 2.选择MySQL数据库 使用mysql_se…

论文排版怕翻车?这个排版神器是时候用起来了!

全世界只有3.14 % 的人关注了青少年数学之旅相信每年临近准备毕设或者毕业论文的同学会遇到这些问题&#xff1a;“我的毕业论文提交一次就被导师批评一次&#xff0c;内容不行就算了&#xff0c;格式也有问题&#xff01;改论文改到绝望”“期刊的版式要求不是统一的&#xff…

fatal error C1001: INTERNAL COMPILER ERROR

http://www.ieasy.org/yuzuo/archives/2005_07.html (余佐的blog)VC6.0的一个编译错误的解决 在window98下使用vc6.0时&#xff0c;如果预编译头文件(stdafx.h)中包含了模板类的头文件&#xff0c;比如atl的头文件时&#xff0c;编译器会报错&#xff1a;fatal error C1001: IN…

.NET Day in China(上海)| 线上线下

点击蓝字关注我们活动简介.NET 6 Preview 6 在 7月14日已经发布&#xff0c;.NET 6 是微软开启全平台统一一个 .NET 计划以来的第一个 LTS 版本&#xff0c;意义重大&#xff0c;微软在 .NET 6 引入了 MAUI&#xff0c;跨平台开发将更为简单&#xff0c;ASP.NET Core 也在不断的…

java综合图形界面程序设计_java综合图形界面程序设计.doc

java综合图形界面程序设计.doc还剩10页未读&#xff0c;继续阅读下载文档到电脑&#xff0c;马上远离加班熬夜&#xff01;亲&#xff0c;喜欢就下载吧&#xff0c;价低环保&#xff01;内容要点&#xff1a;[键入文字]10四、实验小结(包括问题和解决方法、心得体会等)这次课程…

数学知识在游戏中的运用

Transform Vector3 Mathf Lerp,PingPong,三角函数、反三角函数 ,Clamp等 Quatertion Matrix4x4转载于:https://www.cnblogs.com/zhaoqingqing/p/3454444.html

开通博客园,新的网络生活的开始

作者: 笨小窗 作于明德园 E-mail: pgpxc163.com 或许对网络博客真的不是很了解。 流浪于网络上多年&#xff0c;总是想寻找一些满足自己品味的一些博客网站&#xff0c;但所遇到的要不就是网速慢得让人难以忍受&#xff0c;要不就是广告满天飞扬&#xff0c;总之很难找到满足…

[导入]C++程序随笔

C程序的一些随笔文章来源:http://blog.csdn.net/jaopen/archive/2006/03/13/622822.aspx

你有见过从肚子里抽出来的脂肪吗? | 今日趣图

全世界只有3.14 % 的人关注了青少年数学之旅不在家&#xff1f;快递给你放火烧了科普中国我在偷窥你上网...英式没品笑话学校食堂全新版本的空调苍南派轮世界各国的数学水平天秀bot你永远不知道外卖商家还有什么隐藏“绝活”图片迷惑行為大賞你有见过肚子里抽出来的脂肪吗&…

.NET Day in China(上海-7.24)| 线上线下

点击蓝字关注我们活动简介.NET 6 Preview 6 在 7月14日已经发布&#xff0c;.NET 6 是微软开启全平台统一一个 .NET 计划以来的第一个 LTS 版本&#xff0c;意义重大&#xff0c;微软在 .NET 6 引入了 MAUI&#xff0c;跨平台开发将更为简单&#xff0c;ASP.NET Core 也在不断的…

javasript 面向对象

JavaScript. 是一种解释型的、基于对象的脚本语言。尽管与 C、C# 这样成熟的面向对象的语言相比&#xff0c;JavaScript的功能要弱一些&#xff0c;但对于它的预期用途而言&#xff0c;JavaScript的功能已经足够大了。但是由于各种各样的原因&#xff0c;我们在实际进行开发的过…

java 手机 上传图片_在手机端使用拍照功能上传图片的功能的解决文案

主要依赖了一个compress.js的文件&#xff0c;文件内容如下:/** Tencent is pleased to support the open source community by making WeUI.js available.** Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.** Licensed under the MIT License …

砸4亿美元,GE豪赌的全球最大风力发电机到底多大?

全世界只有3.14 % 的人关注了青少年数学之旅叶片长达107米&#xff0c;转子直径为220米&#xff0c;轮毂高度为135米&#xff0c;叶尖最大高度为260米&#xff0c;几乎是纽约自由女神像从地面到火炬尖端高度的三倍。这就是巨头GE豪赌的全球最大风力发电机&#xff1a;Haliade-X…

会计部分关键术语1

accounting equation 会计等式资产等于负债加所有者权益之和。articulation 勾稽关系存在于以相同的基础性交易为基础编制的财务报表之间的密切关系。assets 资产一个实体所拥有的经济资源。balance sheet 资产负债表通过汇总一个企业在某一时点的资产、负债和所有者权益反映企…