Created
December 9, 2016 18:22
-
-
Save david-driscoll/159406b02e9d2d3e805092b82470da0b to your computer and use it in GitHub Desktop.
This file contains hidden or 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
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