Skip to content

HumbleMediator is a simple mediator pattern library for CQRS

License

Notifications You must be signed in to change notification settings

undrivendev/HumbleMediator

Repository files navigation

HumbleMediator

NuGet Build Status Azure DevOps tests Quality Gate Status Coverage

HumbleMediator is a simple library (~50 lines of code) containing the minimum amount of abstractions/boilerplate code to implement a functioning Mediator pattern implementation for CQRS.

It is designed to leverage the functionality provided by a Dependency Injection container, so if you're not using one in your project, this is not for you.

⭐ Like it? Give a star

If you like this project, you learned something from it or you are using it in your applications, please press the star button. Thanks!

Installation

dotnet add package HumbleMediator

Registration

Register the IMediator interface with the Dependency Injection container of your choice by creating an instance of the Mediator class and pass a Func<Type, object?> as a constructor argument.

This delegate should point to the service resolution method of the Dependency Injection container itself.

Some examples:

ASP.NET Core

services.AddSingleton<IMediator>(sp => new Mediator(sp.GetService));

SimpleInjector

container.Register<IMediator>(() => new Mediator(container.GetInstance), Lifestyle.Singleton);

Generic IServiceProvider

container.Register<IMediator>(() => new Mediator((container as IServiceProvider).GetService));

Usage

Create the necessary queries and/or commands by marking the DTOs with the appropriate ICommand<TResult> or IQuery<TResult> interface.

public record CreateCustomerCommand(Customer Customer) : ICommand<int>;

Create a handler for each of those commands and/or queries by creating the necessary handlers implementing the ICommandHandler<TCommand, TResult> or IQueryHandler<TQuery, TResult> interfaces.

public class CreateCustomerCommandHandler : ICommandHandler<CreateCustomerCommand, int>
{
    public async Task<int> Handle(
        CreateCustomerCommand command,
        CancellationToken cancellationToken = default
    )
    {
        // Handler logic
    }
}

Call the handlers via the IMediator interface.

public class CustomersController
{
    private readonly IMediator _mediator;

    public CustomersController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpPost]
    public async Task<ActionResult<int>> Create()
    {
        return await _mediator.SendCommand<CreateCustomerCommand, int>(
            new CreateCustomerCommand(new Customer())
        );
    }
}

Cross-cutting concerns

It's possible to implement cross-cutting concerns by leveraging the Decorator pattern on the mediator or handler interfaces.

By doing that, you'll be able to extend the default behavior with some custom logic that will be executed every time a request to the mediator is made.

Some examples of cross-cutting concerns could be:

  • Logging
  • Validation
  • Caching

and so on.

Samples

A working example in the context of an ASP.NET Web API, including an implementation of cross-cutting concerns, can be found in my other project.

About

HumbleMediator is a simple mediator pattern library for CQRS

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages