C# Academy · Урок

Уведомления и события

Публикуйте доменные события с помощью MediatR.

Урок 4 из 413 шагов

«Уведомления и события» — бесплатный урок C# Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.

Запросы и уведомления

У запроса есть один handler, и он возвращает значение. Уведомление — это широковещательное сообщение: у него может быть ноль или больше обработчиков, и оно ничего не возвращает. Используйте уведомления, чтобы сообщать о произошедшем событии.

// Request:      one handler, returns a result
// Notification: many handlers, fire-and-forget

Уведомление

Событие предметной области — это запись, реализующая INotification. Она описывает факт, произошедший в прошлом.

public record OrderPlacedNotification(int OrderId, int CustomerId)
    : INotification;

INotificationHandler

Каждый подписчик реализует INotificationHandler<TNotification>. Несколько обработчиков могут подписаться на одно уведомление, и каждый будет обрабатывать его независимо.

public class SendConfirmationEmailHandler
    : INotificationHandler<OrderPlacedNotification>
{
    public Task Handle(
        OrderPlacedNotification n, CancellationToken ct)
    {
        // send the email...
        return Task.CompletedTask;
    }
}

Несколько подписчиков

Добавьте столько обработчиков, сколько требуется. Они не знают друг о друге — новые реакции можно добавлять, не изменяя издателя.

public class UpdateInventoryHandler
    : INotificationHandler<OrderPlacedNotification>
{
    public Task Handle(OrderPlacedNotification n, CancellationToken ct)
    {
        // decrement stock...
        return Task.CompletedTask;
    }
}

Публикация

Чтобы вызвать уведомление, внедрите IPublisher (или IMediator) и вызовите Publish. Будет вызван каждый зарегистрированный обработчик.

public class CreateOrderHandler(AppDbContext db, IPublisher publisher)
    : IRequestHandler<CreateOrderCommand, int>
{
    public async Task<int> Handle(CreateOrderCommand c, CancellationToken ct)
    {
        var order = new Order { CustomerId = c.CustomerId };
        db.Orders.Add(order);
        await db.SaveChangesAsync(ct);
        await publisher.Publish(
            new OrderPlacedNotification(order.Id, c.CustomerId), ct);
        return order.Id;
    }
}

Разделение побочных эффектов

Уведомления не дают основному сценарию использования отклоняться от своей задачи. Размещение заказа только сохраняет заказ и публикует событие, а отправка писем и обновление запасов выполняются в собственных обработчиках. Это принцип открытости/закрытости в действии.

// CreateOrderHandler does NOT know about email or inventory

Стратегия публикации

По умолчанию MediatR ожидает каждый обработчик уведомления последовательно. Если один обработчик выдаёт исключение, последующие не запускаются. Вы можете передать собственный компонент публикации, чтобы запускать их параллельно.

builder.Services.AddMediatR(cfg =>
{
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
    cfg.NotificationPublisher = new TaskWhenAllPublisher();
});

Обработка сбоев

Поскольку обработчики независимы, определите, что означает сбой. Для некритичных побочных эффектов перехватывайте исключение и записывайте ошибку в журнал внутри обработчика, чтобы один сбой не нарушал работу остальных.

public async Task Handle(OrderPlacedNotification n, CancellationToken ct)
{
    try { await _email.SendAsync(n.CustomerId, ct); }
    catch (Exception ex) { _logger.LogError(ex, "email failed"); }
}

Шаблон доменных событий

Распространённый подход: сущности накапливают доменные события, а после сохранения транзакции вы публикуете их все. Это гарантирует, что события сработают только после фиксации изменения.

await db.SaveChangesAsync(ct);
foreach (var domainEvent in order.Events)
    await publisher.Publish(domainEvent, ct);
order.Events.Clear();

Уведомления и очереди сообщений

Уведомления MediatR выполняются внутри процесса и синхронно в рамках запроса. Для доставки между службами или гарантированной доставки публикуйте сообщения в настоящий брокер сообщений (например, RabbitMQ или службу сообщений Azure).

// In-process reactions  -> MediatR notifications
// Cross-service / durable -> message broker

Проверка уведомлений

Вы можете проверить, что обработчик публикует нужное событие, передав имитацию IPublisher и убедившись, что был выполнен соответствующий вызов.

var publisher = new Mock<IPublisher>();
var handler = new CreateOrderHandler(db, publisher.Object);
await handler.Handle(new CreateOrderCommand(1, []), default);
publisher.Verify(p => p.Publish(
    It.IsAny<OrderPlacedNotification>(), default), Times.Once);

Быстрая проверка

Подтвердите, что вы поняли модель уведомлений.

Итоги

Вы изучили уведомления и события:

  • INotification — это широковещательное уведомление с нулём или несколькими INotificationHandler.
  • Публикуйте уведомление с помощью IPublisher.Publish, чтобы вызвать всех подписчиков.
  • Уведомления отделяют побочные эффекты и следуют принципу открытости/закрытости.
  • Они выполняются внутри процесса; для событий между службами или гарантированной доставки используйте брокер.

На этом курс по CQRS и MediatR завершён.

Можно начать бесплатно

Изучай C# с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
93
Уроки
346

Часто задаваемые вопросы

Урок «Уведомления и события» бесплатный?

Да — полный текст урока «Уведомления и события» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.

Чему я научусь в уроке «Уведомления и события»?

Публикуйте доменные события с помощью MediatR. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C# Academy?

Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Уведомления и события»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C# Academy?

Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Концепции CQRS
  2. Команды и обработчики с MediatR
  3. Поведения конвейера
  4. Уведомления и события
← Назад к C# Academy