Last active
October 2, 2018 11:18
-
-
Save fabiomaulo/d4d9e06311b0eef45f8f2f14f7c7fcb0 to your computer and use it in GitHub Desktop.
The Meditor framework
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
/// <summary> | |
/// Define an object that encapsulates how a set of objects interact. | |
/// Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. | |
/// </summary> | |
public interface IMediator | |
{ | |
/// <summary> | |
/// Perform a query to the "model". | |
/// </summary> | |
/// <typeparam name="TRequest">The type of the request.</typeparam> | |
/// <typeparam name="TResult">The type of the result of the query.</typeparam> | |
/// <param name="request">The request or the criteria of the query.</param> | |
/// <param name="cancellationToken">The cancelation token.</param> | |
/// <returns>The result of the query.</returns> | |
Task<TResult> Query<TRequest, TResult>(TRequest request, CancellationToken cancellationToken = default(CancellationToken)); | |
} | |
/// <summary> | |
/// Real mediator between the two types. | |
/// </summary> | |
/// <typeparam name="TRequest">Original Type.</typeparam> | |
/// <typeparam name="TResult">Result Type.</typeparam> | |
public interface IMediator<in TRequest, TResult> | |
{ | |
/// <summary> | |
/// Handle the madiation between the two types. | |
/// </summary> | |
/// <param name="request">The original instance of the request to handle.</param> | |
/// <param name="prevResult">The possible previous result when a mediator is executed in a pipeline.</param> | |
/// <param name="cancellationToken">The cancelation token.</param> | |
/// <returns>The result of the mediation.</returns> | |
Task<TResult> Handle(TRequest request, TResult prevResult = default(TResult), CancellationToken cancellationToken = default(CancellationToken)); | |
} | |
public class Mediator : IMediator | |
{ | |
private readonly Func<Type, object> mediatorFactory; | |
public Mediator(Func<Type, object> mediatorFactory) | |
{ | |
this.mediatorFactory = mediatorFactory ?? throw new ArgumentNullException(nameof(mediatorFactory)); | |
} | |
public Task<TResult> Query<TRequest, TResult>(TRequest request, CancellationToken cancellationToken = default(CancellationToken)) | |
{ | |
if (request == null) | |
{ | |
throw new ArgumentNullException(nameof(request)); | |
} | |
var mediatorType = typeof(IMediator<,>).MakeGenericType(typeof(TRequest), typeof(TResult)); | |
var concreteMediator = (IMediator<TRequest, TResult>)mediatorFactory(mediatorType); | |
return concreteMediator.Handle(request, cancellationToken: cancellationToken); | |
} | |
} | |
public class PipelineMediator<TRequest, TResult>: IMediator<TRequest, TResult> | |
{ | |
private readonly IMediator<TRequest, TResult> mediator; | |
public PipelineMediator(IMediator<TRequest, TResult> mediator | |
, IMediator<TRequest, TResult> innerMediator = null) | |
{ | |
this.mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); | |
InnerMediator = innerMediator ?? new NoOpMediator<TRequest, TResult>(); | |
} | |
protected IMediator<TRequest, TResult> InnerMediator { get; } | |
public async Task<TResult> Handle(TRequest request, TResult prevResult = default(TResult), CancellationToken cancellationToken = default(CancellationToken)) | |
{ | |
var r = await mediator.Handle(request, prevResult, cancellationToken); | |
var rr = await InnerMediator.Handle(request, r, cancellationToken); | |
return rr; | |
} | |
} | |
internal class NoOpMediator<TRequest, TResult> : IMediator<TRequest, TResult> | |
{ | |
public Task<TResult> Handle(TRequest request, TResult prevResult = default(TResult), CancellationToken cancellationToken = default(CancellationToken)) | |
{ | |
return Task.FromResult(prevResult); | |
} | |
} | |
public static class MediatorPipelineCreator | |
{ | |
public static IMediator<TRequest, TResult> Then<TRequest, TResult>(this IMediator<TRequest, TResult> outer | |
, IMediator<TRequest, TResult> inner) | |
{ | |
return new PipelineMediator<TRequest, TResult>(outer ?? throw new ArgumentNullException(nameof(outer), "Invalid mediator pipeline.") | |
, inner ?? throw new ArgumentNullException(nameof(inner), "Invalid mediator pipeline.")); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage example
Real world
Registration