TheMediator 1.0.3
dotnet add package TheMediator --version 1.0.3
NuGet\Install-Package TheMediator -Version 1.0.3
<PackageReference Include="TheMediator" Version="1.0.3" />
<PackageVersion Include="TheMediator" Version="1.0.3" />
<PackageReference Include="TheMediator" />
paket add TheMediator --version 1.0.3
#r "nuget: TheMediator, 1.0.3"
#:package TheMediator@1.0.3
#addin nuget:?package=TheMediator&version=1.0.3
#tool nuget:?package=TheMediator&version=1.0.3
TheMediator
<img src="./TheMediator.Core/icon.png" alt="drawing" style="width:200px;"/>
TheMediator é uma implementação de alto desempenho do padrão Mediator para .NET, com suporte a Filters e Notifications. É leve, extensível e rápido, ideal para desacoplar componentes em sistemas.
Esse projeto faz parte da saga "Reinventando a Roda: Criando seu próprio MediatR", onde eu crio uma implementação própria.
Foram 3 posts no total:
- https://dev.to/angelobelchior/reinventando-a-roda-criando-seu-proprio-mediatr-parte-1-3f1o
- https://dev.to/angelobelchior/reinventando-a-roda-criando-seu-proprio-mediatr-parte-2-1c8e
- https://dev.to/angelobelchior/reinventando-a-roda-criando-seu-proprio-mediatr-parte-3-3gp1
Instalação
Você pode instalar o pacote via NuGet usando o seguinte comando:
dotnet add package TheMediator --version 1.0.1
Feito isso, você pode registrar o Mediator no seu projeto:
builder.Services.AddTheMediator(configuration =>
{
configuration.AddServicesFromAssemblies(typeof(Program).Assembly);
configuration.Filters.Add<LoggingFilter>();
configuration.Notifiers.Configurations.DeliveryMode = NotificationDeliveryMode.FireAndForget;
});
Funcionalidades
Handlers
Os Handlers são responsáveis por processar as requisições.
Eles implementam a interface IRequestHandler<TRequest, TResponse>, onde TRequest é o tipo da requisição e TResponse é o tipo da resposta.
TResponse não é obrigatório, e o TRequest pode ser qualquer tipo, incluindo string, int, Guid, etc.
É possível ter mais de um Handler para o mesmo tipo de requisição (TRequest) contanto que o TResponse seja diferente.
Os Handlers são registrados automaticamente pelo método AddServicesFromAssemblies no AddTheMediator.
Exemplo de uso:
public record ProductRequest(string Name, decimal Price);
public record ProductResponse(Guid Id, string Name, decimal Price);
public class CreateProductRequestHandler(IProductsRepository repository)
: IRequestHandler<ProductRequest, ProductResponse>
{
public async Task<ProductResponse> HandleAsync(ProductRequest request, CancellationToken cancellationToken)
{
var created = await repository.Create(request, cancellationToken);
return created;
}
}
public class SearchProductRequestHandler(IProductsRepository repository)
: IRequestHandler<string, IReadOnlyCollection<ProductResponse>?>
{
public Task<IReadOnlyCollection<ProductResponse>?> HandleAsync(
string? query,
CancellationToken cancellationToken)
{
return repository.Search(query, cancellationToken);
}
}
// Exemplo de uso
app.MapPost("/products",
async (
[FromServices] ISender sender,
[FromBody] ProductRequest request,
CancellationToken cancellationToken) =>
{
var response = await sender.SendAsync<ProductRequest, ProductResponse?>(request, cancellationToken);
return response is null
? Results.BadRequest("Cannot create product")
: Results.Created($"/products/{response.Id}", response);
})
.WithName("Products.Post.ProductRequest");
Filters
Os Filters permitem adicionar lógica antes ou depois da execução de um handler, como validações, logging ou manipulação de exceções.
Exemplo de uso:
public class LoggerRequestFilter(ILogger<LoggerRequestFilter> logger)
: IRequestFilter
{
public Task<TResponse> FilterAsync<TRequest, TResponse>(TRequest request, Func<Task<TResponse>> next,
CancellationToken cancellationToken)
where TRequest : notnull
{
logger.LogInformation("{Type} execution started: {Time}", request.GetType().Name, DateTime.Now);
var response = next();
logger.LogInformation("{Type} execution finished: {Time}", request.GetType().Name, DateTime.Now);
return response;
}
}
Os Filters devem ser registrados manualmente no AddTheMediator e a ordem de execução é a ordem em que foram registrados.
Notifications
As Notifications permitem enviar mensagens para múltiplos handlers de forma assíncrona (quando o delivery mode é FireAndForget) ou síncrona (quando o delivery mode é WaitForAll).
O DeliveryMode padrão é FireAndForget, e ele pode ser configurado no AddTheMediator.
As Notifications são registrados automaticamente pelo método AddServicesFromAssemblies no AddTheMediator.
Exemplo de uso:
public class LogInfoProductCreatedNotification(ILogger<LogInfoProductCreatedNotification> logger)
: INotificationHandler<ProductResponse>
{
public async Task HandleAsync(ProductResponse notification, CancellationToken cancellationToken)
{
logger.LogInformation("{Class} Product {ProductName} created", nameof(CreateProductNotification),
notification.Name);
}
}
public class SendEmailProductCreatedNotification(ILogger<SendEmailProductCreatedNotification> logger, IEmailService emailService)
: INotificationHandler<ProductResponse>
{
public async Task HandleAsync(ProductResponse notification, CancellationToken cancellationToken)
{
await emailService.SendAsync($"Product {notification.Name} created...", notification.Dump(), cancellationToken);
}
}
// Exemplo de uso
public class CreateProductRequestHandler(IPublisher publisher, IProductsRepository repository)
: IRequestHandler<ProductRequest, ProductResponse>
{
public async Task<ProductResponse> HandleAsync(ProductRequest request, CancellationToken cancellationToken)
{
var created = await repository.Create(request, cancellationToken);
await publisher.PublishAsync(created, cancellationToken);
return created;
}
}
Logging
O TheMediator utiliza o ILogger para registrar informações sobre as requisições e respostas via método Trace.
Por default, essa opção vem desabilitada.
Para mudar essa configuração é necessário mudar o level do logger no appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"TheMediator.Core": "Trace"
}
}
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.9)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.9)
- System.Threading.Channels (>= 9.0.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.