Skip to content

Instantly share code, notes, and snippets.

@david-driscoll
Created December 9, 2016 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save david-driscoll/159406b02e9d2d3e805092b82470da0b to your computer and use it in GitHub Desktop.
Save david-driscoll/159406b02e9d2d3e805092b82470da0b to your computer and use it in GitHub Desktop.
void Main()
{
var cb = new ContainerBuilder();
cb.RegisterSource(new ContravariantRegistrationSource());
cb.RegisterAssemblyTypes(typeof(IMediator).Assembly).AsImplementedInterfaces();
cb.RegisterAssemblyTypes(this.GetType().Assembly)
.Where(v => v.IsClosedTypeOf(typeof(IAsyncRequestHandler<,>)))
.As(t => t.GetInterfaces()
.Where(v => v.IsClosedTypeOf(typeof(IAsyncRequestHandler<,>)))
.Select(v => new KeyedService(typeof(IAsyncRequestHandler<,>), v)));
cb.RegisterAssemblyTypes(this.GetType().Assembly)
.Where(v => !v.IsClosedTypeOf(typeof(IAsyncRequestHandler<,>)))
.AsImplementedInterfaces();
cb.Register<SingleInstanceFactory>(ctx =>
{
var cc = ctx.Resolve<IComponentContext>();
return t => cc.Resolve(t);
});
cb.Register<MultiInstanceFactory>(ctx =>
{
var cc = ctx.Resolve<IComponentContext>();
return t => (IEnumerable<object>)cc.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
});
cb.RegisterGenericDecorator(typeof(PipelineHandler<,>), typeof(IAsyncRequestHandler<,>), typeof(IAsyncRequestHandler<,>));
var c = cb.Build();
var m = c.Resolve<IMediator>();
var a = m.SendAsync(new Request1()).Result;
}
public interface IPipelineBehavior
{
Task Handle(HandlerContext context, Func<Task> next);
}
class PipelineHandler<TRequest, TResponse> : IAsyncRequestHandler<TRequest, TResponse>
where TRequest : IAsyncRequest<TResponse>
{
private IAsyncRequestHandler<TRequest, TResponse> _handler;
private IEnumerable<IPipelineBehavior> _pipelines;
private Func<HandlerContext , Task> _pipeline;
public PipelineHandler(IAsyncRequestHandler<TRequest, TResponse> handler, IEnumerable<IPipelineBehavior> pipelines)
{
_handler = handler;
_pipelines = pipelines.Reverse();
}
public async Task<TResponse> Handle(TRequest request)
{
var context = new HandlerContext() { Request = request };
await _pipelines.Aggregate(InvokeHandler(context), HandlePipeline(context))();
return (TResponse)context.Response;
}
private Func<Task> InvokeHandler(HandlerContext context)
{
return () => DoHandler(context);
}
private async Task<TResponse> DoHandler(HandlerContext context)
{
var response = await _handler.Handle((TRequest)context.Request);
context.Response = response;
return response;
}
private Func<Func<Task>, IPipelineBehavior, Func<Task>> HandlePipeline(HandlerContext context)
{
return (func, pipeline) => () => pipeline.Handle(context, func);
}
}
public class HandlerContext
{
public object Request { get; internal set; }
public object Response { get; internal set; }
}
class Request1 : IAsyncRequest<Response> { }
class Response { }
class RequestHandler1 : IAsyncRequestHandler<Request1, Response>
{
public async Task<Response> Handle(Request1 request)
{
Console.WriteLine("Response");
return new Response();
}
}
class Pipeline1 : IPipelineBehavior
{
public async Task Handle(HandlerContext context, Func<Task> next)
{
Console.WriteLine(this.GetType().Name + "Start");
await next();
Console.WriteLine(this.GetType().Name + "End");
}
}
class Pipeline2 : IPipelineBehavior
{
public async Task Handle(HandlerContext context, Func<Task> next)
{
Console.WriteLine(this.GetType().Name + "Start");
await next();
Console.WriteLine(this.GetType().Name + "End");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment