手机编码制网站,浅议网络营销论文,公司要建设网站需要那些程序,设计公司网站建设费用最近问了几个面试同一个问题#xff1a;如果有多个自定义Middleware#xff0c;如何控制它们的执行顺序#xff08;比如先判断用户合法再写访问日志#xff09;。居然大部分人答不上来#xff1f;#xff01; 对此#xff0c;你有什么看法#xff1f;ASP.NET Core Midd… 最近问了几个面试同一个问题如果有多个自定义Middleware如何控制它们的执行顺序比如先判断用户合法再写访问日志。居然大部分人答不上来 对此你有什么看法ASP.NET Core Middleware的调用顺序这里我直接贴上官方文档[1]中的图片: ASP.NET Core 请求管道包含一系列请求委托依次调用。而调用顺序实际上就是我们在Startup.cs中注册使用UseMiddlewareExtensions.UseMiddleware方法它们的顺序。示例代码如下public void ConfigureServices(IServiceCollection services)
{//注册生命周期services.AddTransientTransientMiddleware();services.AddScopedScopedMiddleware();
}public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{//注册调用顺序app.UseMiddlewareTransientMiddleware();app.UseMiddlewareScopedMiddleware();
}
但这种方式对于调整自定义Middleware的需求需要经常修改Startup.cs而且会使代码比较凌乱可读性较差。可以使用下面的方式简化注册代码public void ConfigureServices(IServiceCollection services)
{services.AddMiddlewares();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseMiddlewares();
}
实现方式1.定义AttributeMiddlewareRegisterAttribute将放在每个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就把它放入ListMiddlewareRegisterInfo列表中最后根据Sort属性顺序依次注册代码如下public static class MiddlewareRegisterExtensions
{private static readonly IEnumerableMiddlewareRegisterInfo _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 ListMiddlewareRegisterInfo GetMiddlewareRegisterInfos(){var middlewareRegisterInfos new ListMiddlewareRegisterInfo();//所有包含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.GetCustomAttributeMiddlewareRegisterAttribute();if (attribute ! null){middlewareRegisterInfos.Add(new MiddlewareRegisterInfo(type, attribute));}}}return middlewareRegisterInfos.OrderBy(pp.Sort).ToList();}
}
测试一下创建3个Middleware功能仅仅是输出日志[MiddlewareRegister(Sort 100)]
public class OneMiddleware : IMiddleware
{private readonly ILoggerOneMiddleware logger;public OneMiddleware(ILoggerOneMiddleware 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