avatarKonstantin Fedorov

Summary

The provided web content is a comprehensive guide on using MediatR in .NET 8 to implement the mediator design pattern, which simplifies code by separating concerns and facilitating communication between components, and enhancing CQRS (Command Query Responsibility Segregation) practices.

Abstract

The article "šŸš€ Quick Guide: MediatR in .NET 8" introduces developers to the MediatR library, a tool that simplifies complex code by implementing the mediator pattern. This pattern allows different parts of a system to communicate without direct dependencies, promoting loose coupling. The guide explains how to set up MediatR in a .NET project, demonstrates how to use it for CQRS with command and query examples, and shows how to create pipelines for additional features like logging and caching. The author emphasizes that MediatR's ability to keep read and write operations separate leads to cleaner, more maintainable code, and its pipeline features enable developers to add cross-cutting concerns like validation and logging without cluttering the main logic. The article concludes by encouraging the audience to engage with the content and share their thoughts.

Opinions

  • The author believes that MediatR is an excellent tool for developers who want to reduce complexity in their codebase and adhere to the CQRS pattern.
  • MediatR is praised for its ability to manage commands, queries, and notifications efficiently, which is particularly beneficial in the context of CQRS.
  • The guide suggests that using MediatR's pipelines can significantly improve code quality by allowing the addition of features like logging and caching in a non-intrusive manner.
  • The author expresses that the mediator pattern, as implemented by MediatR, is superior for system communication, as it avoids direct dependencies between components.
  • The article conveys enthusiasm for the .NET 8 version of MediatR, implying that it brings notable improvements to the development experience.
  • The author values community engagement and invites readers to participate in discussions about the topic, indicating a collaborative approach to learning and development.

šŸš€ 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ā€¦

Csharp
Dotnet
Cqrs
Mediatr
Programming
Recommended from ReadMedium