共用方式為


.NET .NET Aspire 中的事件

在 .NET.NET Aspire中,事件可讓您在各種 應用程式主控生命週期期間發佈和訂閱事件,。 事件比生命週期事件更有彈性。 這兩者都可以讓您在事件回呼期間執行任意程序代碼,但事件機制提供更精細的事件計時和發佈,以及支援自定義事件。

.NET .NET Aspire 中的事件機制是 📦Aspire的一部分。托管 NuGet 套件。 此套件提供 Aspire.Hosting.Eventing 命名空間中的一組介面和類別,可用來發佈和訂閱 .NET.NET Aspire 應用程式主專案中的事件。 應用程式的事件範圍限定在主機本身及其內部資源之間。

在本文中,您將瞭解如何使用 .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();

上述程式代碼是以 starter 範本為基礎,並新增對 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 資源上的 ResourceReadyEventConnectionStringAvailableEventBeforeResourceStartedEvent 事件。 呼叫 AddRedis 時,它會傳回 IResourceBuilder<T>,其中 TRedisResource。 資源產生器會將資源公開為 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 發佈自定義事件。 若要發佈事件,您必須先將事件定義為 IDistributedApplicationEventIDistributedApplicationResourceEvent 介面的實作。 您必須根據事件是全域應用程式主機事件或資源特定事件,判斷要實作的介面。

然後,您可以藉由呼叫下列其中一個 API 來訂閱和發佈事件:

提供 EventDispatchBehavior

分派事件時,您可以控制事件如何分派給訂閱者。 事件分派行為是透過枚舉 EventDispatchBehavior 來指定的。 以下是可用的行為:

預設行為是「EventDispatchBehavior.BlockingSequential」。 若要覆寫此行為,請在呼叫發佈 API,例如 PublishAsync時,提供所需的行為做為自變數。