Команды и обработчики с MediatR
Направляйте запросы специализированным обработчикам.
«Команды и обработчики с MediatR» — бесплатный урок C# Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Регистрация MediatR
MediatR сканирует сборки, чтобы обнаружить обработчики. Зарегистрируйте его один раз при запуске, указав сборку, содержащую обработчики.
builder.Services.AddMediatR(cfg =>
cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));Интерфейс запроса
Сообщение, ожидающее ответа, реализует IRequest<TResponse>. Параметр типа определяет, что возвращает handler.
public record CreateOrderCommand(int CustomerId, string[] Items)
: IRequest<int>; // returns the new order idКоманды без результата
Если команда не возвращает содержательных данных, реализуйте обобщённый интерфейс IRequest (это сокращённая запись для IRequest<Unit>).
public record CancelOrderCommand(int OrderId) : IRequest;Интерфейс обработчика запроса
Handler реализует IRequestHandler<TRequest, TResponse> и предоставляет метод Handle, в котором выполняется работа.
public class CreateOrderHandler
: IRequestHandler<CreateOrderCommand, int>
{
public Task<int> Handle(
CreateOrderCommand request, CancellationToken ct)
{
// create the order...
return Task.FromResult(newOrderId);
}
}Внедрение зависимостей
Обработчики извлекаются из DI, поэтому они могут получать через конструктор контекст context базы данных, репозитории и другие службы.
public class CreateOrderHandler(AppDbContext db)
: IRequestHandler<CreateOrderCommand, int>
{
public async Task<int> Handle(
CreateOrderCommand request, CancellationToken ct)
{
var order = new Order { CustomerId = request.CustomerId };
db.Orders.Add(order);
await db.SaveChangesAsync(ct);
return order.Id;
}
}Отправитель
Чтобы отправить запрос, внедрите ISender (или более общий IMediator) и вызовите Send. MediatR найдёт подходящий handler.
public class OrdersController(ISender sender) : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Create(CreateOrderCommand cmd)
{
int id = await sender.Send(cmd);
return CreatedAtAction(nameof(Get), new { id }, null);
}
}Отправка в минимальных API
Минимальные API внедряют ISender непосредственно в делегат конечной точки.
app.MapPost("/orders", async (
CreateOrderCommand cmd, ISender sender) =>
{
var id = await sender.Send(cmd);
return Results.Created($"/orders/{id}", new { id });
});Запросы — это тоже сообщения
Запросы используют тот же механизм IRequest / IRequestHandler; различается только намерение: handler читает данные и никогда их не изменяет.
public record GetOrderQuery(int Id) : IRequest<OrderDto?>;
public class GetOrderHandler(AppDbContext db)
: IRequestHandler<GetOrderQuery, OrderDto?>
{
public async Task<OrderDto?> Handle(
GetOrderQuery q, CancellationToken ct) =>
await db.Orders
.Where(o => o.Id == q.Id)
.Select(o => new OrderDto(o.Id, o.Total))
.SingleOrDefaultAsync(ct);
}Один обработчик на запрос
Для Send типу запроса должен соответствовать ровно один handler. Наличие нуля или двух обработчиков для одного запроса — ошибка конфигурации.
// CreateOrderCommand -> exactly one CreateOrderHandlerВозврат содержательных результатов
Ответ может иметь любой тип — объект передачи данных, оболочку результата или даже результат с несколькими вариантами, — позволяя обработчикам явно выражать успех и неудачу.
public record Result(bool Ok, string? Error);
public record PlaceOrderCommand(int Id) : IRequest<Result>;Тестирование обработчика
Поскольку handler — это обычный класс с внедрёнными зависимостями, его можно тестировать напрямую: без HTTP и без контроллера.
var handler = new CreateOrderHandler(inMemoryDb);
var id = await handler.Handle(
new CreateOrderCommand(1, ["sku-1"]), CancellationToken.None);
Assert.True(id > 0);Быстрая проверка
Проверьте, понимаете ли Вы модель отправки MediatR.
Итоги
Вы реализовали команды и обработчики:
AddMediatRсканирует сборки и регистрирует обработчики.- Сообщения реализуют
IRequest<T>, а обработчики —IRequestHandler<TRequest, T>. - Внедрите
ISenderи вызовитеSendдля отправки сообщения; ему соответствует ровно один handler. - Запросы используют тот же механизм и не имеют побочных эффектов.
Далее: поведения конвейера.
Часто задаваемые вопросы
Урок «Команды и обработчики с MediatR» бесплатный?
Да — полный текст урока «Команды и обработчики с MediatR» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «Команды и обработчики с MediatR»?
Направляйте запросы специализированным обработчикам. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Команды и обработчики с MediatR»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Концепции CQRS
- Команды и обработчики с MediatR
- Поведения конвейера
- Уведомления и события