Net Core-MediatR

一 GitHub地址:https://github.com/jbogard/MediatR

有了 MediatR 我们可以在应用中轻松实现 CQRS:
IRequest<> 的消息名称以 Command 为结尾的是命令,其对应的 Handler 执行「写」任务

IRequest<> 的消息名称以 Query 为结尾的是查询,其对应的 Handler 执行「读」数据

二 简单使用

添加nuget包:

dotnet add package MediatR
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection

其他方面

 private readonly ISender _sender;
 public UsersController(ISender sender) => _sender = sender;
var users = await _sender.Send(query, cancellationToken);

1 Send方式:

public class MyRequestMsg : IRequest<int>
{
    public string RequestMsgType { get;set;} = string.Empty;
}
public class MyRequestHandler : IRequestHandler<MyRequestMsg, int>
{
    public Task<int> Handle(MyRequestMsg request, CancellationToken cancellationToken)
    {
        System.Console.WriteLine($"开始处理信息了,消息类型:{request.RequestMsgType}");
        return Task.FromResult(1);
    }
}
builder.Services.AddMediatR( option => {
    option.RegisterServicesFromAssembly(typeof(Program).Assembly);
});

var mediator = builder.Services.BuildServiceProvider().GetRequiredService<IMediator>();
int nResponse = mediator.Send(new MyRequestMsg(){RequestMsgType="Requesttype1"}).Result;
System.Console.WriteLine($"消息处理完成。返回响应{nResponse}");

2 publish方式

public record CreatUser(string Name,string Email) : INotification;

public class CusCreateNotificationHandler : INotificationHandler<CreatUser>
{
    public Task Handle(CreatUser notification, CancellationToken cancellationToken)
    {
        System.Console.WriteLine($"创建用户{notification.Name}");
        return Task.CompletedTask;
    }
}

public class CusUpdateNotificationHandler : INotificationHandler<CreatUser>
{
    public Task Handle(CreatUser notification, CancellationToken cancellationToken)
    {
        System.Console.WriteLine($"同时用户{notification.Email}");
        return Task.CompletedTask;
    }
}
[HttpPost]
public async Task<int> CusCreate( [FromBody] CreatUser cmd,CancellationToken cancellationToken)
{
        _mediator.Publish(cmd, cancellationToken);
        return await Task.FromResult<int>(1); 
}

三,MediatR的管道,netcore的处理方式就是管道,利用RediatR的管理可以实现记录日志,校验参数等功能。

 

public sealed class AppLoggingBehavior<TRequest, IResponse> : IPipelineBehavior<TRequest, IResponse>
    where TRequest : MediatR.IRequest<IResponse>
{
    private readonly ILogger<AppLoggingBehavior<TRequest, IResponse>> _logger;

    public AppLoggingBehavior(ILogger<AppLoggingBehavior<TRequest, IResponse>> logger)
    {
        _logger = logger;
    }

    public async Task<IResponse> Handle(TRequest request, RequestHandlerDelegate<IResponse> next, CancellationToken cancellationToken)
    {
        string requestName = typeof(TRequest).Name;
        string unqiueId = Guid.NewGuid().ToString();
        string requestJson = JsonConvert.SerializeObject(request);
        _logger.LogInformation($"Begin Request Id:{unqiueId}, request name:{requestName}, request json:{requestJson}");
        var timer = new Stopwatch();
        timer.Start();
        var response = await next();
         _logger.LogInformation($"End Request Id:{unqiueId}, request name:{requestName}, total request time:{timer.ElapsedMilliseconds}ms");
        return response;
    }
}

在Program.cs中:

builder.Services.AddMediatR( option => {
    option.RegisterServicesFromAssembly(Assembly.GetEntryAssembly());//typeof(Program).Assembly);
});
builder.Services.AddScoped(typeof(IPipelineBehavior<,>),typeof(AppLoggingBehavior<,>));

即可实现记录日志的功能

四 添加参数校验

using FluentValidation;
using JWTWebApi.Response;
using MediatR;

public class ReuqestValidationBehavior<TRequest, IResponse> : IPipelineBehavior<TRequest, IResponse>
    where TRequest : MediatR.IRequest<IResponse>
    // where IResponse: ResponseResult<IResponse>
{
    private readonly IEnumerable<IValidator<TRequest>> _validators;
    public ReuqestValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
    {
        _validators = validators;
    }

    public async Task<IResponse> Handle(TRequest request, RequestHandlerDelegate<IResponse> next, CancellationToken cancellationToken)
    {
        if (!_validators.Any())
        {
            return await next();
        }

        var context = new ValidationContext<TRequest>(request);

        var errorsDictionary = _validators
           .Select(x => x.Validate(context))
           .SelectMany(x => x.Errors)
           .Where(x => x != null)
           .GroupBy(
               x => x.PropertyName,
               x => x.ErrorMessage,
               (propertyName, errorMessages) => new
               {
                   Key = propertyName,
                   Values = errorMessages.Distinct().ToArray()
               }).ToList();

        if (errorsDictionary.Any())
        {
            // 这里需要修改 throw new ValidationException(string.Join("-",errorsDictionary.Select(x=>x.Key)));//errorsDictionary);
        }

        return await next();
    }
}

public class RequestCreaterUser: IRequest<int>
{
    public string Name{get;set;} = string.Empty;
    public string Email{get;set;} = string.Empty;
}

public class FCreaterUserCommandHandler : IRequestHandler<RequestCreaterUser, int>
{
    public Task<int> Handle(RequestCreaterUser request, CancellationToken cancellationToken)
    {
        System.Console.WriteLine("创建命令!");
        return Task.FromResult(1);
    }
}

public class UserCreateRequestValidator : AbstractValidator<RequestCreaterUser>
{
    public UserCreateRequestValidator()
    {
        RuleFor(c=>c.Name).NotEmpty().MaximumLength(2).WithErrorCode("403").WithMessage("Name长度不能超过2不能为空");
        RuleFor(c=>c.Email).NotEmpty().MaximumLength(2).WithErrorCode("403").WithMessage("Email长度不能超过2不能为空");
    }
}

controller:

[HttpPost]
    public async Task<IActionResult> CreateUserByValider( [FromBody] RequestCreaterUser cmd,CancellationToken cancellationToken)
    {
         await _mediator.Send(cmd, cancellationToken); //send the CusCreateCommand to the user via the IMediator. (optional) 创建消息通
        return NoContent(); //returns a NO CONTENT with HTTP 200 (OK) HTTP 202 (Accepted) HTTP 400 (Bad Request) HTTP 500 (Internal Server
    }

program.cs中注入依赖:

builder.Services.AddValidatorsFromAssembly(Assembly.GetEntryAssembly());
builder.Services.AddMediatR( option => {
    option.RegisterServicesFromAssembly(Assembly.GetEntryAssembly());//typeof(Program).Assembly);
});
builder.Services.AddScoped(typeof(IPipelineBehavior<,>),typeof(ReuqestValidationBehavior<,>));
builder.Services.AddScoped(typeof(IPipelineBehavior<,>),typeof(AppLoggingBehavior<,>));

记一下参考地址:https://blog.51cto.com/u_8130830/6238723

其他待续。。。

posted @ 2023-06-05 10:54  vba是最好的语言  阅读(108)  评论(0编辑  收藏  举报