Last active
March 9, 2023 08:21
-
-
Save zhangr4/153bcfbbcd38a7fdb589c740f8dd8022 to your computer and use it in GitHub Desktop.
a simple implementation like asp.net middleware pipeline
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* just for learning | |
* key concept, LinkedList | |
* refer https://blog.csdn.net/qq_16587307/article/details/104301877 | |
* refer https://medium.com/@bonnotguillaume/software-architecture-the-pipeline-design-pattern-from-zero-to-hero-b5c43d8a4e60 | |
*/ | |
namespace pipeline | |
{ | |
public class Program | |
{ | |
static void Main() | |
{ | |
Context context = new ConcreteContext(); | |
context.Name = "test context"; | |
var pipelineBuilder = new PipelineBuilder(); | |
pipelineBuilder.AddHandler(new ConcreteHandler(name: "hanlder1")); | |
pipelineBuilder.AddHandler(new ConcreteHandler(name: "handler2")); | |
var pipeline = pipelineBuilder.Build(); | |
pipeline.Invoke(context); | |
Console.ReadLine(); | |
} | |
} | |
public abstract class Context | |
{ | |
public virtual string Name { get; set; } = string.Empty; | |
} | |
public class ConcreteContext : Context | |
{ | |
public override string Name { get; set; } = string.Empty; | |
} | |
public interface IHandler | |
{ | |
public Task Invoke(Context context); | |
public void SetNext(IHandler handler); | |
} | |
public class ConcreteHandler : IHandler | |
{ | |
private string _name = string.Empty; | |
public ConcreteHandler() { } | |
public ConcreteHandler(string name) | |
{ | |
_name = name; | |
} | |
private IHandler? _next; //maintain next handler in handler its self or in pipeline | |
public void SetNext(IHandler handler) | |
{ | |
_next = handler; | |
} | |
public async Task Invoke(Context context) | |
{ | |
//do something before | |
Console.WriteLine($"enter handler [{_name}], address context [{context.Name}] and pass to next handler"); | |
await _next!.Invoke(context); | |
Console.WriteLine($"exit handler [{_name}]"); | |
//do something after | |
} | |
} | |
public class DefaultHandler : IHandler | |
{ | |
public Task Invoke(Context context) | |
{ | |
//do nothing | |
Console.WriteLine("default"); | |
return Task.CompletedTask; | |
} | |
public void SetNext(IHandler handler) | |
{ | |
} | |
} | |
public class PipelineBuilder | |
{ | |
private IList<IHandler> _handlers = new List<IHandler>(); | |
public void AddHandler(IHandler handler) | |
{ | |
_handlers.Add(handler); | |
} | |
public IHandler Build() | |
{ | |
IHandler endpoint = new DefaultHandler(); | |
foreach (var handler in _handlers.Reverse()) | |
{ | |
handler.SetNext(endpoint); | |
endpoint = handler; | |
} | |
return endpoint; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Pipeline | |
{ | |
public class HttpContext | |
{ | |
public string Request { get; set; } | |
public string Response { get; set; } | |
} | |
public delegate Task RequestDelegate(HttpContext context); | |
public interface IApplicationBuilder | |
{ | |
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); | |
RequestDelegate Build(); | |
} | |
public class ApplicationBuilder : IApplicationBuilder | |
{ | |
private readonly IList<Func<RequestDelegate, RequestDelegate>> _components | |
= new List<Func<RequestDelegate, RequestDelegate>>(); | |
public RequestDelegate Build() | |
{ | |
RequestDelegate app = async ctx => | |
{ | |
Console.WriteLine("deault middleware"); | |
await Task.CompletedTask; | |
}; | |
foreach (var component in _components.Reverse()) | |
{ | |
app = component(app); | |
} | |
return app; | |
} | |
public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware) | |
{ | |
_components.Add(middleware); | |
return this; | |
} | |
} | |
public static class Extensions | |
{ | |
public static void Run(this IApplicationBuilder appbuilder, RequestDelegate handler) | |
{ | |
if (appbuilder == null) | |
{ | |
throw new ArgumentNullException("app"); | |
} | |
if (handler == null) | |
{ | |
throw new ArgumentNullException(); | |
} | |
appbuilder.Use(_ => handler); | |
} | |
public static IApplicationBuilder Use( | |
this IApplicationBuilder appbuilder, Func<HttpContext, Func<Task>, Task> middleware) | |
{ | |
return appbuilder.Use(next => | |
{ | |
return context => | |
{ | |
Func<Task> simpleNext = () => next(context); | |
return middleware(context, simpleNext); | |
}; | |
}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment