🚀 Quick Guide: MediatR in .NET 8
Hello coder! If you are tired of complex code and want to make things easier, I have good news for you. MediatR is a great tool that creates a special pattern called a mediator. It makes lots of tasks automatic, allowing machines to communicate with each other and achieve great results.
Introduction
MediatR makes it easy to use the mediator design pattern in your apps. It acts like a middleman, ensuring that commands, queries, and notifications are managed well without any confusion. In CQRS, MediatR excels by keeping read and write tasks apart, making your code neater and easier to grow.
Setting Up MediatR
First things first, let’s get MediatR into your project:
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection
Now, let’s wire it up in your Startup.cs
or Program.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMediatR(typeof(Startup));
}
}
CQRS with MediatR — Let’s Do This!
Command Example
Commands are your go-to for making changes in the system. Let’s take a look at a simple CreateOrderCommand
public record CreateOrderCommand(string ProductName, int Quantity) : IRequest<OrderResponse>;
public class CreateOrderHandler : IRequestHandler<CreateOrderCommand, OrderResponse>
{
public Task<OrderResponse> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
{
return Task.FromResult(new OrderResponse { Success = true });
}
}
Query Example
Queries are all about retrieving data without modifying anything. Here’s an example of GetOrderByIdQuery
:
public record GetOrderByIdQuery(int OrderId) : IRequest<Order>;
public class GetOrderByIdHandler : IRequestHandler<GetOrderByIdQuery, Order>
{
public Task<Order> Handle(GetOrderByIdQuery request, CancellationToken cancellationToken)
{
return Task.FromResult(new Order { Id = request.OrderId, ProductName = "Sample Product" });
}
}
Making Pipelines
Mediator pipelines allow you to add useful features such as logging, validation, and caching, without disrupting your main logic.
Behaviors allow you to wrap your request-handling logic in additional features.
Logging Behavior
Would you like to log every request? Here’s how:
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;
public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
{
_logger = logger;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
_logger.LogInformation($"Handling {typeof(TRequest).Name}");
var response = await next();
_logger.LogInformation($"Handled {typeof(TResponse).Name}");
return response;
}
}
Cache Behavior
Speed things up with caching:
public class CacheBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
private readonly IMemoryCache _cache;
private readonly ILogger<CacheBehavior<TRequest, TResponse>> _logger;
public CacheBehavior(IMemoryCache cache, ILogger<CacheBehavior<TRequest, TResponse>> logger)
{
_cache = cache;
_logger = logger;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
var cacheKey = request.GetHashCode().ToString();
if (_cache.TryGetValue(cacheKey, out TResponse response))
{
_logger.LogInformation($"Returning cached response for {typeof(TRequest).Name}");
return response;
}
_logger.LogInformation($"Cache miss for {typeof(TRequest).Name}. Invoking handler.");
response = await next();
_cache.Set(cacheKey, response, TimeSpan.FromMinutes(5));
return response;
}
}
Registration
To control the order in which mediator pipelines are executed in MediatR, you can register the behaviors in the desired order in the startup configuration of your application.
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(ServicesExtensions).Assembly));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(CacheBehavior<,>));
Conclusion
The MediatR in .NET 8 is great for CQRS. It has neat pipeline features. You can add logging, checking, caching, and more. This keeps your code clean and sturdy. Whether you’re working with actions, requests, or alerts, the Mediator makes life simple. This lets you concentrate on your business rules without stressing about the technical parts.
👏 If you find this content helpful, I’d appreciate it if you could give it a clap (you can clap more than once by holding down the button). Also, I’m encouraging you to leave your thoughts and suggestions in the comments so we can continue to discuss this topic.
Thanks for reading…