Zachowania potoku
Dodawaj logikę przekrojową za pomocą zachowań.
Zachowania potoku to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 3 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.
Aspekty przekrojowe
Logowanie, walidacja, pomiary czasu i transakcje dotyczą wielu handlerów. Powielanie tego kodu w każdym handlerze jest monotonne i podatne na błędy.
Zachowania pipeline'u MediatR pozwalają otoczyć każdy request wspólną logiką.
// One behavior runs around all handlersIPipelineBehavior
Zachowanie implementuje IPipelineBehavior<TRequest, TResponse>. Jego metoda Handle otrzymuje request oraz delegat next, który wywołuje pozostałą część pipeline'u.
public class LoggingBehavior<TRequest, TResponse>
: IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken ct)
{
// before
var response = await next();
// after
return response;
}
}Delegat next
next() wywołuje kolejne zachowanie albo właściwy handler, jeśli jest to ostatni element. Kod przed wywołaniem działa podczas przechodzenia w głąb pipeline'u, a kod po wywołaniu - podczas powrotu.
// [Behavior A in] -> [Behavior B in] -> [Handler]
// <- [Behavior B out] <- [A out]Zachowanie rejestrujące
Konkretne zachowanie rejestrujące zapisuje nazwę requestu przy wejściu oraz czas, który upłynął, przy wyjściu.
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken ct)
{
var name = typeof(TRequest).Name;
_logger.LogInformation("Handling {Name}", name);
var sw = Stopwatch.StartNew();
var response = await next();
_logger.LogInformation("{Name} took {Ms}ms", name, sw.ElapsedMilliseconds);
return response;
}Rejestrowanie zachowania
Należy zarejestrować otwarte zachowanie generyczne w DI. MediatR zastosuje je do każdego requestu.
builder.Services.AddTransient(
typeof(IPipelineBehavior<,>),
typeof(LoggingBehavior<,>));Zachowanie walidujące
Popularnym zastosowaniem jest walidacja requestów za pomocą FluentValidation. Zachowanie uruchamia wszystkie walidatory przed wykonaniem handlera i zgłasza wyjątek, jeśli którykolwiek z nich zakończy się niepowodzeniem.
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken ct)
{
var context = new ValidationContext<TRequest>(request);
var failures = _validators
.Select(v => v.Validate(context))
.SelectMany(r => r.Errors)
.Where(f => f is not null)
.ToList();
if (failures.Count != 0)
throw new ValidationException(failures);
return await next();
}Przerywanie pipeline'u
Zachowanie może całkowicie pominąć handler, zwracając wynik bez wywołania next() - jest to przydatne przy buforowaniu wyników zapytań lub odrzucaniu nieprawidłowych requestów.
if (_cache.TryGet(key, out TResponse cached))
return cached; // handler never runs
var response = await next();
_cache.Set(key, response);
return response;Kolejność zachowań
Zachowania są wykonywane w kolejności rejestracji. Należy umieścić logowanie najbardziej na zewnątrz, następnie walidację, a potem transakcje, aby każde zachowanie prawidłowo otaczało kolejne.
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(TransactionBehavior<,>));Zachowanie transakcyjne
Należy objąć handlery komend transakcją bazy danych, aby cała operacja została atomowo zatwierdzona albo wycofana.
await using var tx = await _db.Database.BeginTransactionAsync(ct);
try
{
var response = await next();
await tx.CommitAsync(ct);
return response;
}
catch
{
await tx.RollbackAsync(ct);
throw;
}Stosowanie tylko do określonych requestów
Należy użyć interfejsu znacznikowego i ograniczenia generycznego, aby zachowanie dotyczyło tylko requestów, które wyraźnie je włączają - na przykład tylko komendy mogą otrzymywać obsługę transakcji.
public interface ITransactional { }
public record CreateOrderCommand(...) : IRequest<int>, ITransactional;
// where TRequest : ITransactionalDlaczego zachowania są lepsze od middleware
W przeciwieństwie do middleware zachowania uruchamiają się dla każdej wiadomości, mają dostęp do typowanego requestu i odpowiedzi oraz działają nawet wtedy, gdy request jest przekazywany poza HTTP, np. z zadania w tle.
// Strongly typed, transport-independent cross-cutting logicSzybki test
Proszę potwierdzić sposób działania zachowań.
Podsumowanie
Poznali Państwo zachowania pipeline'u:
IPipelineBehavior<TRequest, TResponse>otacza każdy request wspólną logiką.- Delegat
nextprzesuwa request dalej w pipeline'ie; pominięcie go przerywa działanie handlera. - Typowe zastosowania to logowanie, walidacja, transakcje i buforowanie.
- Zachowania są wykonywane w kolejności rejestracji i są silnie typowane.
Następnie: powiadomienia i zdarzenia.
Ucz się C# dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 93
- Lekcje
- 346
Często zadawane pytania
Czy lekcja „Zachowania potoku” jest bezpłatna?
Tak — pełny tekst „Zachowania potoku” 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 „Zachowania potoku”?
Dodawaj logikę przekrojową za pomocą zachowań. Ć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 3 z 4.
Ile czasu zajmuje lekcja „Zachowania potoku”?
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.