Sdílet prostřednictvím


Vlastní příkazy prostředků v .NET.NET Aspire

Každý prostředek v modelu aplikace .NET.NET Aspire je reprezentován jako IResource a když je přidán do nástroje pro vytváření distribuovaných aplikací , stává se parametrem obecného typu v rozhraní IResourceBuilder<T>. Pomocí rozhraní API pro vytváření prostředků můžete řetězit volání, konfigurovat základní prostředek a v některých situacích přidat do prostředku vlastní příkazy. Běžnými scénáři pro vytvoření vlastního příkazu mohou být migrace databází, naplňování nebo resetování databáze. V tomto článku se dozvíte, jak přidat vlastní příkaz do Redis prostředku, který vymaže mezipaměť.

Důležitý

Tyto příkazy řídicího panelu .NET.NET Aspire jsou k dispozici pouze při místním spuštění řídicího panelu. Nejsou k dispozici při spuštění řídicího panelu v Azure Container Apps.

Přidejte vlastní příkazy do prostředku

Začněte vytvořením nové úvodní aplikace .NET.NET Aspire z dostupných šablon. Pokud chcete vytvořit řešení z této šablony, postupujte podle rychlého startu: Sestavte první .NET.NET Aspire řešení. Po vytvoření tohoto řešení přidejte novou třídu s názvem RedisResourceBuilderExtensions.cs do projektu hostitele aplikace . Obsah souboru nahraďte následujícím kódem:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;

namespace Aspire.Hosting;

internal static class RedisResourceBuilderExtensions
{
    public static IResourceBuilder<RedisResource> WithClearCommand(
        this IResourceBuilder<RedisResource> builder)
    {
        builder.WithCommand(
            name: "clear-cache",
            displayName: "Clear Cache",
            executeCommand: context => OnRunClearCacheCommandAsync(builder, context),
            updateState: OnUpdateResourceState,
            iconName: "AnimalRabbitOff",
            iconVariant: IconVariant.Filled);

        return builder;
    }

    private static async Task<ExecuteCommandResult> OnRunClearCacheCommandAsync(
        IResourceBuilder<RedisResource> builder,
        ExecuteCommandContext context)
    {
        var connectionString = await builder.Resource.GetConnectionStringAsync() ??
            throw new InvalidOperationException(
                $"Unable to get the '{context.ResourceName}' connection string.");

        await using var connection = ConnectionMultiplexer.Connect(connectionString);

        var database = connection.GetDatabase();

        await database.ExecuteAsync("FLUSHALL");

        return CommandResults.Success();
    }

    private static ResourceCommandState OnUpdateResourceState(
        UpdateCommandStateContext context)
    {
        var logger = context.ServiceProvider.GetRequiredService<ILogger<Program>>();

        if (logger.IsEnabled(LogLevel.Information))
        {
            logger.LogInformation(
                "Updating resource state: {ResourceSnapshot}",
                context.ResourceSnapshot);
        }

        return context.ResourceSnapshot.HealthStatus is HealthStatus.Healthy
            ? ResourceCommandState.Enabled
            : ResourceCommandState.Disabled;
    }
}

Předchozí kód:

  • Sdílí obor názvů Aspire.Hosting, aby byl viditelný pro projekt hostitele aplikace.
  • Je to static class, aby mohl obsahovat rozšiřující metody.
  • Definuje jedinou rozšiřující metodu nazvanou WithClearCommand, která rozšiřuje rozhraní IResourceBuilder<RedisResource>.
  • Metoda WithClearCommand zaregistruje příkaz s názvem clear-cache, který vymaže mezipaměť prostředku Redis.
  • Metoda WithClearCommand vrátí instanci IResourceBuilder<RedisResource>, která umožňuje řetězení.

Rozhraní API WithCommand přidává příslušné anotace k prostředku, které jsou využívány na řídicím panelu .NET.NET Aspire. Řídicí panel používá tyto poznámky k vykreslení příkazu v uživatelském rozhraní. Než se k těmto podrobnostem dostanete příliš daleko, nejprve se ujistěte, že rozumíte parametrům metody WithCommand:

  • name: Název příkazu, který se má vyvolat.
  • displayName: Název příkazu, který se má zobrazit na řídicím panelu.
  • executeCommand: Func<ExecuteCommandContext, Task<ExecuteCommandResult>>, který se spustí, když je příkaz vyvolán, což je místo, kde je implementována logika příkazu.
  • updateState: Zpětné volání Func<UpdateCommandStateContext, ResourceCommandState> je vyvoláno k určení stavu "enabled" příkazu, který slouží k povolení nebo zakázání příkazu na řídicím panelu.
  • iconName: Název ikony, která se má zobrazit na řídicím panelu. Ikona je volitelná, ale když ji zadáte, měla by to být platná uživatelské rozhraní Fluent Blazor název ikony.
  • iconVariant: Varianta ikony, která se má zobrazit na řídicím panelu, jsou platné možnosti Regular (výchozí) nebo Filled.

Logika spuštění příkazu

executeCommand delegát je to místo, kde je implementována logika příkazů. Tento parametr je definován jako Func<ExecuteCommandContext, Task<ExecuteCommandResult>>. ExecuteCommandContext poskytuje následující vlastnosti:

  • ExecuteCommandContext.ServiceProvider: Instance IServiceProvider, která se používá k řešení služeb.
  • ExecuteCommandContext.ResourceName: Název instance prostředku, na které se příkaz spouští.
  • ExecuteCommandContext.CancellationToken: CancellationToken, která slouží ke zrušení provádění příkazu.

V předchozím příkladu se delegát executeCommand implementuje jako metoda async, která vymaže mezipaměť prostředku Redis. Deleguje funkci s vymezenou privátní třídou s názvem OnRunClearCacheCommandAsync k provedení skutečného vymazání mezipaměti. Vezměte v úvahu následující kód:

private static async Task<ExecuteCommandResult> OnRunClearCacheCommandAsync(
    IResourceBuilder<RedisResource> builder,
    ExecuteCommandContext context)
{
    var connectionString = await builder.Resource.GetConnectionStringAsync() ??
        throw new InvalidOperationException(
            $"Unable to get the '{context.ResourceName}' connection string.");

    await using var connection = ConnectionMultiplexer.Connect(connectionString);

    var database = connection.GetDatabase();

    await database.ExecuteAsync("FLUSHALL");

    return CommandResults.Success();
}

Předchozí kód:

  • Načte připojovací řetězec z prostředku Redis.
  • Připojí se k instanci Redis.
  • Získá instanci databáze.
  • Spustí příkaz FLUSHALL, který vymaže mezipaměť.
  • Vrátí CommandResults.Success() objekt, který naznačuje, že příkaz byl úspěšný.

Aktualizace logiky stavu příkazu

Delegát updateState je místem, kde se určuje stav příkazu. Tento parametr je definován jako Func<UpdateCommandStateContext, ResourceCommandState>. UpdateCommandStateContext poskytuje následující vlastnosti:

  • UpdateCommandStateContext.ServiceProvider: Instance IServiceProvider, která se používá k řešení služeb.
  • UpdateCommandStateContext.ResourceSnapshot: Snímek instance prostředku, na které se příkaz spouští.

Neměnný snímek je instance CustomResourceSnapshot, která odhaluje různé cenné podrobnosti o instanci prostředku. Vezměte v úvahu následující kód:

private static ResourceCommandState OnUpdateResourceState(
    UpdateCommandStateContext context)
{
    var logger = context.ServiceProvider.GetRequiredService<ILogger<Program>>();

    if (logger.IsEnabled(LogLevel.Information))
    {
        logger.LogInformation(
            "Updating resource state: {ResourceSnapshot}",
            context.ResourceSnapshot);
    }

    return context.ResourceSnapshot.HealthStatus is HealthStatus.Healthy
        ? ResourceCommandState.Enabled
        : ResourceCommandState.Disabled;
}

Předchozí kód:

  • Načte instanci protokolovacího nástroje od poskytovatele služeb.
  • Zaznamenává podrobnosti snímku prostředku.
  • Vrátí ResourceCommandState.Enabled, pokud je prostředek v pořádku; v opačném případě vrátí ResourceCommandState.Disabled.

Otestování vlastního příkazu

Pokud chcete vlastní příkaz otestovat, aktualizujte soubor Program.cs projektu hostitele aplikace tak, aby obsahoval následující kód:

var builder = DistributedApplication.CreateBuilder(args);

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

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

Předchozí kód volá rozšiřující metodu WithClearCommand pro přidání vlastního příkazu do prostředku Redis. Spusťte aplikaci a přejděte na řídicí panel .NET.NET Aspire. Měli byste vidět vlastní příkaz uvedený ve zdroji Redis. Na řídicím panelu na stránce Prostředky vyberte v sloupci Akce tlačítko se třemi tečkami:

řídicí panel .NET Aspire: Redis prostředek mezipaměti se zobrazeným vlastním příkazem.

Předchozí obrázek ukazuje povel Vymazat mezipaměť, který byl přidán do Redis zdroje. Ikona se zobrazí jako přeškrtnutý králík, což označuje, že rychlost závislého prostředku je resetována.

Výběrem příkazu Vymazat mezipaměť vymažte mezipaměť prostředku Redis. Příkaz by se měl úspěšně spustit a mezipaměť by se měla vymazat:

řídicí panel .NET Aspire: Redis prostředek mezipaměti s vlastním příkazem spuštěným.

Viz také