MediatR을 사용하여 .NET Core에서 CQRS 구현
12297 단어 DDD.NETCoreASP.NET_CoreCQRS
개요
MS docs에는 CQRS 및 DDD를 적용한 구현 패턴에 대한 기사가 있습니다.
htps : // / cs. mic로소 ft. 코 m / 쟈 jp / t t t / r 치 테 c 얽힌 / 미 c 로세 r ㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜ
거기에서는 MediatR이라는 라이브러리를 이용해 CQRS의 구현을 실시하고 있습니다.
이번에는 자기 이해의 의미도 담아 도메인 모델과 Web API 구현 샘플을 작성해 보겠습니다.
또한 CQRS와 DDD에 대한 자세한 해설은 전문 여러분에게 맡깁니다.
(※) 필자도 공부중의 몸입니다. . .
코드 샘플
샘플 코드를 Github에 올리고 있습니다.
htps : // 기주 b. 코 m / 쵸시 유키 / t t-t-e-mea tr-mp ぇ
참고
도메인 모델의 코드는, 이하를 참고로 했습니다.
htps : // 기주 b. 코 m / rs ぃ b / 흠뻑 pdd ぇ r pprt
환경
샘플 코드를 Github에 올리고 있습니다.
htps : // 기주 b. 코 m / 쵸시 유키 / t t-t-e-mea tr-mp ぇ
참고
도메인 모델의 코드는, 이하를 참고로 했습니다.
htps : // 기주 b. 코 m / rs ぃ b / 흠뻑 pdd ぇ r pprt
환경
해설
샘플 코드의 프로젝트 구성은 다음과 같습니다.
프로젝트 이름
설명
DotNetCoreMediatrSample.Domain
도메인 모델
DotNetCoreMediatrSample.Infrastructure.InMemory
메모리 내 리포지토리 구현
DotNetCoreMediatrSample.Infrastructure.InMemory.Test
메모리 내 리포지토리 테스트
DotNetCoreMediatrSample.Web
웹 API
이번에는 User 엔터티를 검색하는 쿼리와 User 엔터티를 만드는 명령을 구현합니다.
IRequest 를 구현한 클래스를 각각 작성합니다.
GetUserQuery.cs
public class GetUserQuery : IRequest<UserModel>
{
public GetUserQuery(string id)
{
Id = id;
}
public string Id { get; }
}
CreateUserCommand.cs
public class CreateUserCommand : IRequest
{
public CreateUserCommand(string userName, string firstName, string familyName)
{
UserName = userName;
FirstName = firstName;
FamilyName = familyName;
}
public string UserName { get; }
public string FirstName { get; }
public string FamilyName { get; }
}
MediatR은 쿼리 명령 메시지에 해당하는 작업을 수행하는 Handler를 구현해야합니다.
IRequestHandler 를 구현하는 형태로 작성합니다.
이번 구현 샘플에는 포함되어 있지 않지만 IRequest 대신 INotification을 이용하면 하나의 메시지에 대해 여러 Handler를 등록할 수 있습니다.
GetUserHandler.cs
public class GetUserHandler : IRequestHandler<GetUserQuery, UserModel>
{
private readonly IUserRepository _repository;
public GetUserHandler(IUserRepository repository)
{
_repository = repository;
}
public Task<UserModel> Handle(GetUserQuery request, CancellationToken cancellationToken)
{
var user = _repository.Find(new UserId(request.Id));
var model = user == null ? null : new UserModel(user);
return Task.FromResult(model);
}
}
위의 내용을 ASP.NET Core 웹 API에 통합해 봅니다.
MediatR의 Handler를 DI 컨테이너에 등록합니다. 전용의 확장 메소드가 있기 때문에, 이것을 이용합니다.
또한 메모리 내 리포지토리를 함께 DI 컨테이너에 등록합니다.
실용적인 CQRS에서는 쿼리와 명령으로 대상 데이터 스토어를 구분하는 경우가 있지만 이번에는 동일한 리포지토리입니다.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMediatR(typeof(GetUserHandler).Assembly);
services.AddMediatR(typeof(CreateUserHandler).Assembly);
services.AddControllers();
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "Web API", Version = "v1"}); });
services.AddTransient<IUserRepository, InMemoryUserRepository>();
services.AddTransient<IUserFactory, UserFactory>();
}
Web API의 컨트롤러에서 IMediator를 생성자 주입합니다.
IMediator.Send를 사용하여 쿼리 및 명령을 실행합니다.
UsersController.cs
public UsersController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet("{id}")]
public async Task<ActionResult<UserViewModel>> Get(string id)
{
var user = await _mediator.Send(new GetUserQuery(id));
if (user == null) return BadRequest("データが存在しません");
return new UserViewModel
{
Id = user.Id,
UserName = user.UserName,
FirstName = user.Name.FirstName,
FamilyName = user.Name.FamilyName
};
}
동작 확인은 Swagger UI에서 수행합니다.
MediatR을 사용하면 비교적 쉽게 도메인 로직과 Web API 종속성을 느슨하게 결합 할 수 있습니다.
ASP.NET Core를 사용할 때 선택의 하나로 고려해야 할 가치가 있습니까?
Reference
이 문제에 관하여(MediatR을 사용하여 .NET Core에서 CQRS 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/wasimaru/items/5ad064aac7fc6f929cd1
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
public class GetUserQuery : IRequest<UserModel>
{
public GetUserQuery(string id)
{
Id = id;
}
public string Id { get; }
}
public class CreateUserCommand : IRequest
{
public CreateUserCommand(string userName, string firstName, string familyName)
{
UserName = userName;
FirstName = firstName;
FamilyName = familyName;
}
public string UserName { get; }
public string FirstName { get; }
public string FamilyName { get; }
}
public class GetUserHandler : IRequestHandler<GetUserQuery, UserModel>
{
private readonly IUserRepository _repository;
public GetUserHandler(IUserRepository repository)
{
_repository = repository;
}
public Task<UserModel> Handle(GetUserQuery request, CancellationToken cancellationToken)
{
var user = _repository.Find(new UserId(request.Id));
var model = user == null ? null : new UserModel(user);
return Task.FromResult(model);
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMediatR(typeof(GetUserHandler).Assembly);
services.AddMediatR(typeof(CreateUserHandler).Assembly);
services.AddControllers();
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "Web API", Version = "v1"}); });
services.AddTransient<IUserRepository, InMemoryUserRepository>();
services.AddTransient<IUserFactory, UserFactory>();
}
public UsersController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet("{id}")]
public async Task<ActionResult<UserViewModel>> Get(string id)
{
var user = await _mediator.Send(new GetUserQuery(id));
if (user == null) return BadRequest("データが存在しません");
return new UserViewModel
{
Id = user.Id,
UserName = user.UserName,
FirstName = user.Name.FirstName,
FamilyName = user.Name.FamilyName
};
}
Reference
이 문제에 관하여(MediatR을 사용하여 .NET Core에서 CQRS 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/wasimaru/items/5ad064aac7fc6f929cd1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)