MediatR and ...
서론
MediatR 을 이용하는 여러가지 방법에 대해 알아보자.
Request/Response
IRequest 를 통해 Command 를 생성하고
IRequestHandler <CommandType, OutputType> 을 통해 handler 처리
1 | public class Ping : IRequest<string> { } |
1 2 3 4 5 6 7 | public class PingHandler : IRequestHandler<Ping, string> { public Task<string> Handle(Ping request, CancellationToken cancellationToken) { return Task.FromResult("Pong"); } } |
1 2 | var response = await mediator.Send(new Ping()); Debug.WriteLine(response); // "Pong" |
해당 event 전송 방식은 response 가 올때 까지 대기 하는 방식 이다.
Response 가 없을 경우에 처리.
1 2 3 4 5 6 7 8 | public class OneWay : IRequest { } public class OneWayHandlerWithBaseClass : AsyncRequestHandler<OneWay> { protected override Task Handle(OneWay request, CancellationToken cancellationToken) { // Twiddle thumbs } } |
Notification
INotification 을 통해 Command 를 생성하고
INotificationHandler<CommandType> 을 통해 handler 처리
Request/Response 방식과의 차이점은 response 의 유무와 1:1 이냐 1:n 이냐의 차이이다.
Request 는 Response 를 대기 하지만
Notification 은 publish 후 잊어버린다.
Notification 은 publish 후 잊어버린다.
1 | public class Ping : INotification { } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Pong1 : INotificationHandler<Ping> { public Task Handle(Ping notification, CancellationToken cancellationToken) { Debug.WriteLine("Pong 1"); return Task.CompletedTask; } } public class Pong2 : INotificationHandler<Ping> { public Task Handle(Ping notification, CancellationToken cancellationToken) { Debug.WriteLine("Pong 2"); return Task.CompletedTask; } } |
1 | await mediator.Publish(new Ping()); |
PipeLineBehavior
MediatR 의 execute 전과 후에 작업을 추가 할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class AppLoggingBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> { private readonly ILogger<AppLoggingBehaviour<TRequest, TResponse>> _logger; public AppLoggingBehaviour(ILogger<AppLoggingBehaviour<TRequest, TResponse>> logger) { _logger = logger; } public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next) { string requestName = typeof(TRequest).Name; string unqiueId = Guid.NewGuid().ToString(); _logger.LogInformation($"Begin Request Id:{unqiueId}," + $" request name:{requestName},\nRequest = " + $"{JsonSerializer.Serialize(request,new JsonSerializerOptions{WriteIndented = true})}"); var timer = new Stopwatch(); timer.Start(); var response = await next(); timer.Stop(); _logger.LogInformation($"Begin Request Id:{unqiueId}, " + $"request name:{requestName},\nResponse = " + $"{JsonSerializer.Serialize(response,new JsonSerializerOptions { WriteIndented = true })}" + $"\ntotal request time:{timer.ElapsedMilliseconds}"); return response; } } |
Program.cs 에 서비스 등록
Request , Response 추가
public class GetUserRequest:IRequest<UserResponse> { public string UserId { get; set; } = string.Empty } public class UserResponse { public string Id { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; }
Handler 추가
public class GetUserRequestHandler : IRequestHandler<GetUserRequest, UserResponse> { private List<UserResponse> _userResponses = new List<UserResponse>() { new UserResponse { Id = "1", Name="First", Email = "First@email.com" }, new UserResponse { Id = "2", Name="Second", Email = "Second@email.com" }, new UserResponse { Id = "3", Name="Third", Email = "Third@email.com" }, }; public async Task<UserResponse> Handle(GetUserRequest request, CancellationToken cancellationToken) { var user = _userResponses.Where(u => u.Id.Equals(request.UserId, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (user == null) throw new Exception("Not found user"); return await Task.FromResult(user!); } }
Controller 에 method 추가
[HttpGet("ping")] public async Task<string> SendPing() { await _mediator.Send(new Ping()); return "pong"; } [HttpGet("user")] public async Task<UserResponse> GetUser(string id) { return await _mediator.Send(new GetUserRequest { UserId = id }); } |
Test

댓글
댓글 쓰기