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
其他待续。。。