0Pricing
C# Academy · Lekcja

Powiadomienia i zdarzenia

Publikuj zdarzenia domenowe za pomocą MediatR.

Powiadomienia i zdarzenia to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.

Requesty a powiadomienia

Request ma jednego handlera i zwraca wartość. Powiadomienie jest komunikatem rozgłoszeniowym: ma zero lub więcej handlerów i niczego nie zwraca. Powiadomień należy używać do ogłaszania, że coś się wydarzyło.

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

INotification

Zdarzenie domenowe jest rekordem implementującym INotification. Opisuje fakt wyrażony w czasie przeszłym.

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

INotificationHandler

Każdy subskrybent implementuje INotificationHandler<TNotification>. Wiele handlerów może subskrybować to samo powiadomienie, a każdy z nich obsługuje je niezależnie.

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

Wielu subskrybentów

Należy dodać tyle handlerów, ile potrzeba. Żaden z nich nie wie o pozostałych — nowe reakcje można dodawać bez modyfikowania wydawcy.

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

Publikowanie

Aby wysłać powiadomienie, należy wstrzyknąć IPublisher (lub IMediator) i wywołać Publish. Wywoływany jest każdy zarejestrowany handler.

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;
    }
}

Rozdzielanie efektów ubocznych

Powiadomienia pozwalają skupić główny przypadek użycia na jego zadaniu. Złożenie zamówienia jedynie zapisuje zamówienie i publikuje zdarzenie, a wysyłanie wiadomości e-mail oraz obsługa magazynu znajdują się we własnych handlerach. To zasada otwartości/zamkniętości w praktyce.

// CreateOrderHandler does NOT know about email or inventory

Strategia publikowania

Domyślnie MediatR oczekuje na każdy handler powiadomienia sekwencyjnie. Jeśli jeden z nich zgłosi wyjątek, kolejne handlery nie zostaną uruchomione. Można dostarczyć własnego publish'a, aby uruchamiać je równolegle.

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

Obsługa błędów

Ponieważ handlery są niezależne, należy określić znaczenie ewentualnej awarii. W przypadku niekrytycznych efektów ubocznych należy przechwycić błąd i zapisać go w logu wewnątrz handlera, aby jedna awaria nie zakłócała działania pozostałych.

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

Wzorzec zdarzeń domenowych

Typowy wzorzec polega na tym, że encje gromadzą zdarzenia domenowe, a po zapisaniu transakcji publikuje się je wszystkie. Gwarantuje to, że zdarzenia zostaną wywołane tylko wtedy, gdy zmiana zostanie zatwierdzona.

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

Powiadomienia a kolejki komunikatów

Powiadomienia MediatR działają wewnątrz procesu i synchronicznie w ramach żądania. W przypadku komunikacji między usługami lub trwałego dostarczania należy zamiast tego publikować komunikaty do rzeczywistego brokera wiadomości (np. RabbitMQ lub Azure Service Bus).

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

Testowanie powiadomień

Można sprawdzić, czy handler publikuje właściwe zdarzenie, przekazując atrapę IPublisher i asercją potwierdzając, że został wywołany.

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);

Szybkie sprawdzenie

Należy potwierdzić zrozumienie modelu powiadomień.

Podsumowanie

Omówiono powiadomienia i zdarzenia:

  • INotification to komunikat rozgłaszany do zera lub większej liczby elementów INotificationHandler.
  • Powiadomienia publikuje się za pomocą IPublisher.Publish, aby wywołać wszystkich subskrybentów.
  • Powiadomienia rozdzielają efekty uboczne i realizują zasadę otwartości/zamkniętości.
  • Działają wewnątrz procesu; w przypadku zdarzeń między usługami lub wymagających trwałego dostarczenia należy użyć brokera.

Na tym kończy się kurs CQRS i MediatR.

Często zadawane pytania

Czy lekcja „Powiadomienia i zdarzenia” jest bezpłatna?

Tak — pełny tekst „Powiadomienia i zdarzenia” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Powiadomienia i zdarzenia”?

Publikuj zdarzenia domenowe za pomocą MediatR. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C# Academy?

Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Powiadomienia i zdarzenia”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?

Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Koncepcje CQRS
  2. Polecenia i programy obsługi z MediatR
  3. Zachowania potoku
  4. Powiadomienia i zdarzenia
← Powrót do C# Academy