0Pricing
C# Academy · レッスン

MediatRによるコマンドとハンドラー

リクエストを専用ハンドラーにディスパッチします。

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

MediatR の登録

MediatR はアセンブリをスキャンしてハンドラーを検出します。ハンドラーを含むアセンブリを指定し、起動時に一度登録します。

builder.Services.AddMediatR(cfg =>
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

IRequest

レスポンスを要求するメッセージは IRequest<TResponse> を実装します。型パラメーターは、ハンドラーが返す値の型です。

public record CreateOrderCommand(int CustomerId, string[] Items)
    : IRequest<int>;   // returns the new order id

結果を返さないコマンド

コマンドが意味のある値を返さない場合は、非ジェネリックの IRequest(IRequest<Unit> の省略形)を実装します。

public record CancelOrderCommand(int OrderId) : IRequest;

IRequestHandler

ハンドラーは IRequestHandler<TRequest, TResponse> を実装し、処理を行う Handle メソッドを提供します。

public class CreateOrderHandler
    : IRequestHandler<CreateOrderCommand, int>
{
    public Task<int> Handle(
        CreateOrderCommand request, CancellationToken ct)
    {
        // create the order...
        return Task.FromResult(newOrderId);
    }
}

依存関係の注入

ハンドラーは DI から解決されるため、コンストラクターを通してデータベースコンテキスト、リポジトリ、その他のサービスを受け取れます。

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

ISender

リクエストをディスパッチするには、ISender(または、より広いインターフェイスである IMediator)を注入し、Send を呼び出します。MediatR が対応するハンドラーを見つけます。

public class OrdersController(ISender sender) : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> Create(CreateOrderCommand cmd)
    {
        int id = await sender.Send(cmd);
        return CreatedAtAction(nameof(Get), new { id }, null);
    }
}

Minimal API での Send

Minimal API では、ISender をエンドポイントデリゲートに直接注入します。

app.MapPost("/orders", async (
    CreateOrderCommand cmd, ISender sender) =>
{
    var id = await sender.Send(cmd);
    return Results.Created($"/orders/{id}", new { id });
});

クエリも単なるリクエスト

クエリも同じ IRequest / IRequestHandler の仕組みを使用します。違いは意図だけで、ハンドラーは読み取りを行い、状態を変更することはありません。

public record GetOrderQuery(int Id) : IRequest<OrderDto?>;

public class GetOrderHandler(AppDbContext db)
    : IRequestHandler<GetOrderQuery, OrderDto?>
{
    public async Task<OrderDto?> Handle(
        GetOrderQuery q, CancellationToken ct) =>
        await db.Orders
            .Where(o => o.Id == q.Id)
            .Select(o => new OrderDto(o.Id, o.Total))
            .SingleOrDefaultAsync(ct);
}

リクエストごとに 1 つのハンドラー

Send では、リクエストの型に一致するハンドラーが必ず 1 つ必要です。同じリクエストに対してハンドラーが 0 個または 2 個登録されている場合は、構成エラーになります。

// CreateOrderCommand -> exactly one CreateOrderHandler

豊富な結果を返す

レスポンスには DTO、結果ラッパー、判別可能な結果など、任意の型を使用できます。これにより、ハンドラーで成功と失敗を明示的に表現できます。

public record Result(bool Ok, string? Error);
public record PlaceOrderCommand(int Id) : IRequest<Result>;

ハンドラーのテスト

ハンドラーは依存関係を注入される通常のクラスなので、HTTP やコントローラーを必要とせず、直接テストできます。

var handler = new CreateOrderHandler(inMemoryDb);
var id = await handler.Handle(
    new CreateOrderCommand(1, ["sku-1"]), CancellationToken.None);
Assert.True(id > 0);

理解度チェック

MediatR のディスパッチモデルを確認しましょう。

まとめ

コマンドとハンドラーを実装しました。

  • AddMediatR がアセンブリをスキャンしてハンドラーを登録します。
  • メッセージは IRequest<T> を実装し、ハンドラーは IRequestHandler<TRequest, T> を実装します。
  • ISender を注入して Send を呼び出すとディスパッチされ、対応するハンドラーは必ず 1 つになります。
  • クエリも同じ仕組みを再利用し、副作用を起こさないようにします。

次は、パイプラインビヘイビアについて学びます。

よくある質問

「MediatRによるコマンドとハンドラー」レッスンは無料ですか?

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

「MediatRによるコマンドとハンドラー」で何を学びますか?

リクエストを専用ハンドラーにディスパッチします。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「MediatRによるコマンドとハンドラー」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

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