VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • 让 .NET 轻松构建中间件模式代码

让 .NET 轻松构建中间件模式代码

Intro#

在 asp.net core 中中间件的设计令人叹为观止,如此高大上的设计何不集成到自己的代码里呢。

于是就有了封装了一个简单通用的中间件模板的想法,以后有需要的时候就可以拿来即用。

接口定义#

这里按执行的委托是同步还是异步分为了同步和异步两种构建方法


Copy
//没有返回值的同步中间件构建器 public interface IPipelineBuilder<TContext> { IPipelineBuilder<TContext> Use(Func<Action<TContext>, Action<TContext>> middleware); Action<TContext> Build(); } // 异步中间件构建器 public interface IAsyncPipelineBuilder<TContext> { IAsyncPipelineBuilder<TContext> Use(Func<Func<TContext, Task>, Func<TContext, Task>> middleware); Func<TContext, Task> Build(); }

为了方便使用,定义一下扩展方法,使得可以像 asp.net core 中 app.Use(Fun<HttpContext, Func<Task>, Task>) 一样比较方便的使用,扩展方法定义如下:


Copy
public static IPipelineBuilder<TContext> Use<TContext>(this IPipelineBuilder<TContext> builder, Action<TContext, Action> action) { return builder.Use(next => context => { action(context, () => next(context)); }); } public static IAsyncPipelineBuilder<TContext> Use<TContext>(this IAsyncPipelineBuilder<TContext> builder, Func<TContext, Func<Task>, Task> func) { return builder.Use(next => context => { return func(context, () => next(context)); }); }

为了方便创建对应的 PipelineBuilder ,这里定义了两个方法:

使用 Create 方法就可以创建一个 IPipelineBuilder ,使用 CreateAsync 就可以创建一个 IAsyncPipelineBuilder


Copy
public class PipelineBuilder { public static IPipelineBuilder<TContext> Create<TContext>(Action<TContext> completeAction) { return new PipelineBuilder<TContext>(completeAction); } public static IAsyncPipelineBuilder<TContext> CreateAsync<TContext>(Func<TContext, Task> completeFunc) { return new AsyncPipelineBuilder<TContext>(completeFunc); } }

使用示例#

来看一个使用示例,这里的示例修改自设计模式里的责任链模式的一个示例,废话不说,来看代码:

这是一个请假的示例,不同的请假时间交由不同的审批主管进行审批,最后模拟了从请假1小时到请假8小时的申请处理情况


Copy
private class RequestContext { public string RequesterName { get; set; } public int Hour { get; set; } } public static void Test() { var requestContext = new RequestContext() { RequesterName = "Kangkang", Hour = 12, }; var builder = PipelineBuilder.Create<RequestContext>(context => { Console.WriteLine($"{context.RequesterName} {context.Hour}h apply failed"); }) .Use((context, next) => { if (context.Hour <= 2) { Console.WriteLine("pass 1"); } else { next(); } }) .Use((context, next) => { if (context.Hour <= 4) { Console.WriteLine("pass 2"); } else { next(); } }) .Use((context, next) => { if (context.Hour <= 6) { Console.WriteLine("pass 3"); } else { next(); } }) ; var requestPipeline = builder.Build(); foreach (var i in Enumerable.Range(1, 8)) { Console.WriteLine(); Console.WriteLine($"--------- h:{i} apply Pipeline------------------"); requestContext.Hour = i; requestPipeline.Invoke(requestContext); Console.WriteLine("----------------------------"); Console.WriteLine(); } } public static async Task AsyncPipelineBuilderTest() { var requestContext = new RequestContext() { RequesterName = "Michael", Hour = 12, }; var builder = PipelineBuilder.CreateAsync<RequestContext>(context => { Console.WriteLine($"{context.RequesterName} {context.Hour}h apply failed"); return Task.CompletedTask; }) .Use(async (context, next) => { if (context.Hour <= 2) { Console.WriteLine("pass 1"); } else { await next(); } }) .Use(async (context, next) => { if (context.Hour <= 4) { Console.WriteLine("pass 2"); } else { await next(); } }) .Use(async (context, next) => { if (context.Hour <= 6) { Console.WriteLine("pass 3"); } else { await next(); } }) ; var requestPipeline = builder.Build(); foreach (var i in Enumerable.Range(1, 8)) { Console.WriteLine($"--------- h:{i} apply AsyncPipeline------------------"); requestContext.Hour = i; await requestPipeline.Invoke(requestContext); Console.WriteLine("----------------------------"); } }

运行效果:

实现代码#


Copy
internal class PipelineBuilder<TContext> : IPipelineBuilder<TContext> { private readonly Action<TContext> _completeFunc; private readonly IList<Func<Action<TContext>, Action<TContext>>> _pipelines = new List<Func<Action<TContext>, Action<TContext>>>(); public PipelineBuilder(Action<TContext> completeFunc) { _completeFunc = completeFunc; } public IPipelineBuilder<TContext> Use(Func<Action<TContext>, Action<TContext>> middleware) { _pipelines.Add(middleware); return this; } public Action<TContext> Build() { var request = _completeFunc; foreach (var pipeline in _pipelines.Reverse()) { request = pipeline(request); } return request; } } internal class AsyncPipelineBuilder<TContext> : IAsyncPipelineBuilder<TContext> { private readonly Func<TContext, Task> _completeFunc; private readonly IList<Func<Func<TContext, Task>, Func<TContext, Task>>> _pipelines = new List<Func<Func<TContext, Task>, Func<TContext, Task>>>(); public AsyncPipelineBuilder(Func<TContext, Task> completeFunc) { _completeFunc = completeFunc; } public IAsyncPipelineBuilder<TContext> Use(Func<Func<TContext, Task>, Func<TContext, Task>> middleware) { _pipelines.Add(middleware); return this; } public Func<TContext, Task> Build() { var request = _completeFunc; foreach (var pipeline in _pipelines.Reverse()) { request = pipeline(request); } return request; } }

Reference#

  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/DotNetCoreSample/PipelineTest.cs
  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Helpers/Pipelines/PipelineBuilder.cs
  • https://github.com/dotnet/aspnetcore/blob/master/src/Http/Http/src/Builder/ApplicationBuilder.cs

作者: WeihanLi



相关教程