0Pricing
C# Academy · レッスン

パイプラインビヘイビアー

ビヘイビアーで横断的な処理を追加します。

「パイプラインビヘイビアー」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

横断的関心事

ロギング、検証、計測、トランザクションは多くのハンドラーに適用されます。そのコードを各ハンドラーにコピーすると、冗長でエラーが発生しやすくなります。

MediatR のパイプラインビヘイビアを使うと、共通ロジックですべてのリクエストをラップできます。

// One behavior runs around all handlers

IPipelineBehavior

ビヘイビアは IPipelineBehavior<TRequest, TResponse> を実装します。その Handle メソッドは、リクエストと、パイプラインの残りを呼び出す next デリゲートを受け取ります。

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

next デリゲート

next() は次のビヘイビアを呼び出します。これが最後のビヘイビアの場合は、実際のハンドラーを呼び出します。呼び出しの前に記述したコードは処理の入り口で実行され、呼び出しの後に記述したコードは出口で実行されます。

// [Behavior A in] -> [Behavior B in] -> [Handler]
//               <- [Behavior B out] <- [A out]

ロギングビヘイビア

具体的なロギングビヘイビアでは、処理の入り口でリクエスト名を記録し、出口で経過時間を記録します。

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

ビヘイビアの登録

オープンジェネリックのビヘイビアを DI に登録します。MediatR がすべてのリクエストに適用します。

builder.Services.AddTransient(
    typeof(IPipelineBehavior<,>),
    typeof(LoggingBehavior<,>));

検証ビヘイビア

よく使われる用途の 1 つが、FluentValidation によるリクエスト検証です。ビヘイビアはハンドラーの実行前にすべてのバリデーターを実行し、1 つでも失敗すると例外をスローします。

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

ショートサーキット

ビヘイビアは next() を呼び出さずに戻ることで、ハンドラー全体をスキップできます。クエリ結果のキャッシュや、無効なリクエストの拒否に役立ちます。

if (_cache.TryGet(key, out TResponse cached))
    return cached;          // handler never runs
var response = await next();
_cache.Set(key, response);
return response;

ビヘイビアの順序

ビヘイビアは登録された順序で実行されます。ロギングを最外側に置き、次に検証、最後にトランザクションを置くと、それぞれが正しく次の処理をラップします。

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(TransactionBehavior<,>));

トランザクションビヘイビア

コマンドハンドラーをデータベーストランザクションでラップし、操作全体をアトミックにコミットまたはロールバックできるようにします。

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

特定のリクエストへの適用

マーカーインターフェイスとジェネリック制約を使うと、適用を選択したリクエストにだけビヘイビアを適用できます。たとえば、トランザクションをコマンドだけに適用できます。

public interface ITransactional { }
public record CreateOrderCommand(...) : IRequest<int>, ITransactional;

// where TRequest : ITransactional

ミドルウェアよりビヘイビアが適している理由

HTTP ミドルウェアとは異なり、ビヘイビアはメッセージごとに実行され、型付きのリクエストとレスポンスを扱えます。また、HTTP の外部(例:バックグラウンドジョブ)からリクエストをディスパッチした場合でも動作します。

// Strongly typed, transport-independent cross-cutting logic

理解度チェック

ビヘイビアの動作を確認しましょう。

まとめ

パイプラインビヘイビアを学びました。

  • IPipelineBehavior<TRequest, TResponse> が共通ロジックですべてのリクエストをラップします。
  • next デリゲートがパイプラインを先に進めます。これをスキップするとハンドラーをショートサーキットできます。
  • 一般的な用途は、ロギング、検証、トランザクション、キャッシュです。
  • ビヘイビアは登録順に実行され、強い型付けが適用されます。

次は、通知とイベントについて学びます。

よくある質問

「パイプラインビヘイビアー」レッスンは無料ですか?

はい。「パイプラインビヘイビアー」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「パイプラインビヘイビアー」で何を学びますか?

ビヘイビアーで横断的な処理を追加します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「パイプラインビヘイビアー」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. CQRSの概念
  2. MediatRによるコマンドとハンドラー
  3. パイプラインビヘイビアー
  4. 通知とイベント
← C# Academyに戻る