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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- CQRSの概念
- MediatRによるコマンドとハンドラー
- パイプラインビヘイビアー
- 通知とイベント