Skip to content

Instantly share code, notes, and snippets.

@khellang
Last active March 3, 2016 09:50
Show Gist options
  • Select an option

  • Save khellang/bd59065433ee450a9cc2 to your computer and use it in GitHub Desktop.

Select an option

Save khellang/bd59065433ee450a9cc2 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public delegate Task AppFunc(IDictionary<string, object> env);
public delegate AppFunc MidFunc(AppFunc next);
public delegate MidFunc MidFactoryFunc(IDictionary<string, object> props);
public delegate void BuildFunc(MidFactoryFunc factory);
public static class Program
{
public static void Main()
{
var factories = new Stack<MidFactoryFunc>();
Configure(factories.Push);
var middleware = BuildMiddleware(factories);
var app = ComposePipeline(middleware);
ListenForRequests(app);
// Result:
// ClassMiddleware: Begin
// FunctionMiddleware: Begin
// FunctionMiddleware: End
// ClassMiddleware: End
}
private static void Configure(BuildFunc builder)
{
builder.UseClassMiddleware();
builder.UseFunctionMiddleware();
}
private static IEnumerable<MidFunc> BuildMiddleware(IEnumerable<MidFactoryFunc> factories)
{
var props = new Dictionary<string, object>();
// Build the middleware using the startup properties.
return factories.Select(factory => factory(props)).ToArray();
}
private static AppFunc ComposePipeline(IEnumerable<MidFunc> middleware)
{
var end = new AppFunc(_ => Task.FromResult(0));
// Build our pipeline. The last AppFunc is terminating.
return middleware.Aggregate(end, (current, next) => next(current));
}
private static void ListenForRequests(AppFunc app)
{
var hasRequest = true;
while (hasRequest)
{
var env = new Dictionary<string, object>();
app(env); // Invoke our pipeline using the environment.
hasRequest = string.IsNullOrEmpty(Console.ReadLine());
}
}
}
public static class MiddlewareBuilderExtensions
{
public static void UseClassMiddleware(this BuildFunc builder)
{
builder(props => next => new ClassMiddleware(next).Invoke);
}
public static void UseFunctionMiddleware(this BuildFunc builder)
{
builder(props => next => async env =>
{
Console.WriteLine("FunctionMiddleware: Begin");
await next(env);
Console.WriteLine("FunctionMiddleware: End");
});
}
}
public class ClassMiddleware
{
public ClassMiddleware(AppFunc next)
{
Next = next;
}
private AppFunc Next { get; }
public async Task Invoke(IDictionary<string, object> env)
{
Console.WriteLine("ClassMiddleware: Begin");
await Next(env);
Console.WriteLine("ClassMiddleware: End");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment