次の方法で共有


.NET .NET Aspire でのイベント

.NET .NET Aspireでは、イベントを利用すると、さまざまな アプリホストライフサイクル中にイベントの発行およびサブスクライブが可能です。 イベントは、ライフサイクル イベントよりも柔軟です。 どちらもイベント コールバック中に任意のコードを実行できますが、イベント処理では、イベントのタイミング、発行、およびカスタム イベントのサポートを細かく制御できます。

.NET .NET Aspire のイベントメカニズムは、📦Aspireの一部です。NuGet パッケージ ホストします。 このパッケージには、.NET.NET Aspire アプリ ホスト プロジェクトのイベントの発行とサブスクライブに使用する、Aspire.Hosting.Eventing 名前空間のインターフェイスとクラスのセットが用意されています。 イベントのスコープは、アプリ ホスト自体と内部のリソースです。

この記事では、.NET.NET Aspireでイベント機能を使用する方法について説明します。

アプリホストのイベント管理

次のイベントはアプリ ホストで使用でき、次の順序で発生します。

  1. BeforeStartEvent: このイベントは、アプリ ホストが起動する前に発生します。
  2. AfterEndpointsAllocatedEvent: このイベントは、アプリが割り当てられたエンドポイントをホストした後に発生します。
  3. AfterResourcesCreatedEvent: このイベントは、アプリ ホストがリソースを作成した後に発生します。

上記のすべてのイベントは、アプリ ホストのライフ サイクルに似ています。 つまり、IDistributedApplicationLifecycleHook の実装では、これらのイベントを同じように処理できます。 ただし、イベント API では、これらのイベントが発生したときに任意のコードを実行し、イベントによってカスタム イベント (IDistributedApplicationEvent インターフェイスを実装する任意のイベント) を定義できます。

アプリホストイベントに登録する

組み込みのアプリ ホスト イベントをサブスクライブするには、イベント API を使用します。 分散アプリケーション ビルダー インスタンスを作成したら、IDistributedApplicationBuilder.Eventing プロパティにアクセスし、Subscribe<T>(Func<T,CancellationToken,Task>) API を呼び出します。 次のサンプル アプリ ホスト Program.cs ファイルについて考えてみましょう。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache");

var apiService = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");

builder.AddProject<Projects.AspireApp_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithReference(cache)
    .WaitFor(cache)
    .WithReference(apiService)
    .WaitFor(apiService);

builder.Eventing.Subscribe<BeforeStartEvent>(
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("1. BeforeStartEvent");

        return Task.CompletedTask;
    });

builder.Eventing.Subscribe<AfterEndpointsAllocatedEvent>(
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("2. AfterEndpointsAllocatedEvent");

        return Task.CompletedTask;
    });

builder.Eventing.Subscribe<AfterResourcesCreatedEvent>(
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("3. AfterResourcesCreatedEvent");

        return Task.CompletedTask;
    });

builder.Build().Run();

上記のコードは、Subscribe API への呼び出しを追加したスターター テンプレートに基づいています。 Subscribe<T> API は、イベントのサブスクライブ解除に使用できる DistributedApplicationEventSubscription インスタンスを返します。 通常、アプリホストがシャットダウンされるとアプリ全体が破棄されるため、イベントのサブスクライブを解除する必要はないので、返されるサブスクリプションを破棄するのが一般的です。

アプリ ホストを実行すると、.NET.NET Aspire ダッシュボードが表示される時点までに、コンソールに次のログ出力が表示されます。

info: Program[0]
      1. BeforeStartEvent
info: Aspire.Hosting.DistributedApplication[0]
      Aspire version: 9.0.0
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
      Application host directory is: ..\AspireApp\AspireApp.AppHost
info: Program[0]
      2. AfterEndpointsAllocatedEvent
info: Aspire.Hosting.DistributedApplication[0]
      Now listening on: https://localhost:17178
info: Aspire.Hosting.DistributedApplication[0]
      Login to the dashboard at https://localhost:17178/login?t=<YOUR_TOKEN>
info: Program[0]
      3. AfterResourcesCreatedEvent
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application started. Press Ctrl+C to shut down.

ログ出力は、イベント ハンドラーがアプリ ホストのライフ サイクル イベントの順序で実行されることを確認します。 サブスクリプションの順序は、実行順序には影響しません。 BeforeStartEvent が最初にトリガーされ、次に AfterEndpointsAllocatedEventがトリガーされ、最後に AfterResourcesCreatedEventがトリガーされます。

リソースイベント管理

アプリ ホスト イベントに加えて、リソース イベントをサブスクライブすることもできます。 リソース イベントは、個々のリソースに固有に発生します。 リソース イベントは、IDistributedApplicationResourceEvent インターフェイスの実装として定義されます。 次のリソース イベントは、一覧に示されている順序で使用できます。

  1. ConnectionStringAvailableEvent: 接続文字列がリソースで使用可能になったときに発生します。
  2. BeforeResourceStartedEvent: オーケストレーターが新しいリソースを開始する前にトリガーされます。
  3. ResourceReadyEvent: リソースが最初に準備完了状態に遷移したときに発生します。

リソース イベントをサブスクライブする

リソース イベントをサブスクライブするには、イベント API を使用します。 分散アプリケーション ビルダー インスタンスを作成したら、IDistributedApplicationBuilder.Eventing プロパティにアクセスし、Subscribe<T>(IResource, Func<T,CancellationToken,Task>) API を呼び出します。 次のサンプル アプリ ホスト Program.cs ファイルについて考えてみましょう。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache");

builder.Eventing.Subscribe<ResourceReadyEvent>(
    cache.Resource,
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("3. ResourceReadyEvent");

        return Task.CompletedTask;
    });

builder.Eventing.Subscribe<BeforeResourceStartedEvent>(
    cache.Resource,
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("2. BeforeResourceStartedEvent");

        return Task.CompletedTask;
    });

builder.Eventing.Subscribe<ConnectionStringAvailableEvent>(
    cache.Resource,
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("1. ConnectionStringAvailableEvent");

        return Task.CompletedTask;
    });

var apiService = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");

builder.AddProject<Projects.AspireApp_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithReference(cache)
    .WaitFor(cache)
    .WithReference(apiService)
    .WaitFor(apiService);

builder.Build().Run();

上記のコードは、cache リソースの ResourceReadyEventConnectionStringAvailableEvent、および BeforeResourceStartedEvent イベントをサブスクライブします。 AddRedis が呼び出されると、TRedisResourceである IResourceBuilder<T> が返されます。 リソース ビルダーは、リソースを IResourceBuilder<T>.Resource プロパティとして公開します。 その後、対象のリソースが Subscribe API に渡され、リソース上のイベントをサブスクライブします。

アプリ ホストを実行すると、.NET.NET Aspire ダッシュボードが表示される時点までに、コンソールに次のログ出力が表示されます。

info: Aspire.Hosting.DistributedApplication[0]
      Aspire version: 9.0.0
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
      Application host directory is: ..\AspireApp\AspireApp.AppHost
info: Program[0]
      1. ConnectionStringAvailableEvent
info: Program[0]
      2. BeforeResourceStartedEvent
info: Program[0]
      3. ResourceReadyEvent
info: Aspire.Hosting.DistributedApplication[0]
      Now listening on: https://localhost:17222
info: Aspire.Hosting.DistributedApplication[0]
      Login to the dashboard at https://localhost:17222/login?t=<YOUR_TOKEN>
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application started. Press Ctrl+C to shut down.

手記

一部のイベントがブロックされています。 たとえば、BeforeResourceStartEvent が発行されると、特定のリソースのそのイベントのすべてのサブスクリプションの実行が完了するまで、リソースの起動はブロックされます。 イベントがブロックされているかどうかは、イベントの発行方法によって異なります (次のセクションを参照)。

イベントを発行する

いずれかの組み込みイベントをサブスクライブする場合、アプリ ホスト オーケストレーターがユーザーに代わって組み込みイベントを発行するために管理するため、イベントを自分で発行する必要はありません。 ただし、イベント API を使用してカスタム イベントを発行できます。 イベントを発行するには、まず、IDistributedApplicationEvent インターフェイスまたは IDistributedApplicationResourceEvent インターフェイスの実装としてイベントを定義する必要があります。 イベントがグローバル アプリ ホスト イベントかリソース固有のイベントかに基づいて、実装するインターフェイスを決定する必要があります。

その後、次のいずれかの API を呼び出して、イベントをサブスクライブして発行できます。

EventDispatchBehavior を指定する

イベントがディスパッチされるときに、イベントをサブスクライバーにディスパッチする方法を制御できます。 イベント ディスパッチ動作は、EventDispatchBehavior 列挙型で指定されます。 次の動作を使用できます。

既定の動作は EventDispatchBehavior.BlockingSequentialです。 この動作をオーバーライドするには、PublishAsyncなどの発行 API を呼び出すときに、必要な動作を引数として指定します。