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-forgetINotification
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 inventoryStrategia 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 brokerTestowanie 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:
INotificationto komunikat rozgłaszany do zera lub większej liczby elementówINotificationHandler.- 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
- Koncepcje CQRS
- Polecenia i programy obsługi z MediatR
- Zachowania potoku
- Powiadomienia i zdarzenia