Udostępnij za pośrednictwem


Polecenia zasobów niestandardowych w .NET.NET Aspire

Każdy zasób w modelu aplikacji .NET.NET Aspire jest reprezentowany jako IResource, a po dodaniu do konstruktora aplikacji rozproszonej staje się parametrem typu ogólnego interfejsu IResourceBuilder<T>. Używasz konstruktora zasobów interfejsu API, który służy do tworzenia łańcuchów wywołań, konfigurowania bazowego zasobu, a w niektórych sytuacjach możesz chcieć dodać polecenia niestandardowe do zasobu. W niektórych typowych scenariuszach tworzenia polecenia niestandardowego mogą być uruchamiane migracje bazy danych lub inicjalizacja/resetowanie bazy danych. Z tego artykułu dowiesz się, jak dodać niestandardowe polecenie do zasobu Redis, który czyści pamięć podręczną.

Ważny

Te polecenia .NET.NET Aspire pulpitu są dostępne tylko podczas uruchamiania pulpitu lokalnie. Nie są one dostępne podczas uruchamiania pulpitu nawigacyjnego w Azure Container Apps.

Dodawanie poleceń niestandardowych do zasobu

Zacznij od utworzenia nowej aplikacji początkowej .NET.NET Aspire na podstawie dostępnych szablonów . Aby utworzyć rozwiązanie na podstawie tego szablonu, postępuj zgodnie z przewodnikiem Szybki start : Tworzenie pierwszego rozwiązania .NET.NET Aspire. Po utworzeniu tego rozwiązania dodaj nową klasę o nazwie RedisResourceBuilderExtensions.cs do projektu hosta aplikacji . Zastąp zawartość pliku następującym kodem:

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;
    }
}

Powyższy kod:

  • Udostępnia przestrzeń nazw Aspire.Hosting, aby była widoczna dla projektu hostującego aplikację.
  • Jest static class, dzięki czemu może zawierać metody rozszerzenia.
  • Definiuje pojedynczą metodę rozszerzenia o nazwie WithClearCommand, rozszerzając interfejs IResourceBuilder<RedisResource>.
  • Metoda WithClearCommand rejestruje polecenie o nazwie clear-cache, które czyści pamięć podręczną zasobu Redis.
  • Metoda WithClearCommand zwraca wystąpienie IResourceBuilder<RedisResource>, aby umożliwić łączenie łańcucha.

Interfejs API WithCommand dodaje odpowiednie adnotacje do zasobu, które są wykorzystywane w konsoli zarządzania .NET.NET Aspire. Pulpit nawigacyjny używa tych adnotacji do renderowania polecenia w interfejsie użytkownika. Przed przejściem do tych szczegółów upewnij się, że najpierw poznasz parametry metody WithCommand:

  • name: nazwa polecenia do wywołania.
  • displayName: nazwa polecenia do wyświetlenia na pulpicie nawigacyjnym.
  • executeCommand: Func<ExecuteCommandContext, Task<ExecuteCommandResult>> do uruchomienia, gdy polecenie zostanie wywołane, gdzie zaimplementowano logikę polecenia.
  • updateState: wywołanie zwrotne Func<UpdateCommandStateContext, ResourceCommandState> jest wywoływane w celu określenia stanu "włączone" polecenia, który służy do włączania lub wyłączania polecenia na pulpicie nawigacyjnym.
  • iconName: nazwa ikony do wyświetlenia na pulpicie nawigacyjnym. Ikona jest opcjonalna, ale jeśli ją podasz, powinna być prawidłową nazwą ikony Fluent UI Blazor.
  • iconVariant: wariant ikony do wyświetlenia na pulpicie nawigacyjnym, prawidłowe opcje to Regular (wartość domyślna) lub Filled.

Wykonywanie logiki poleceń

Delegat executeCommand to miejsce implementacji logiki poleceń. Ten parametr jest definiowany jako Func<ExecuteCommandContext, Task<ExecuteCommandResult>>. ExecuteCommandContext udostępnia następujące właściwości:

  • ExecuteCommandContext.ServiceProvider: wystąpienie IServiceProvider używane do rozwiązywania usług.
  • ExecuteCommandContext.ResourceName: nazwa wystąpienia zasobu, na którym jest wykonywane polecenie.
  • ExecuteCommandContext.CancellationToken: CancellationToken, które jest używane do anulowania wykonywania polecenia.

W poprzednim przykładzie delegat executeCommand jest implementowany jako metoda async, która czyści pamięć podręczną zasobu Redis. Przekazuje zadanie do prywatnej funkcji w zakresie klasy o nazwie OnRunClearCacheCommandAsync, aby przeprowadzić faktyczne czyszczenie pamięci podręcznej. Rozważ następujący kod:

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

Powyższy kod:

  • Pobiera parametry połączenia z zasobu Redis.
  • Nawiązuje połączenie z wystąpieniem Redis.
  • Pobiera wystąpienie bazy danych.
  • Wykonuje polecenie FLUSHALL, aby wyczyścić pamięć podręczną.
  • Zwraca wystąpienie CommandResults.Success(), aby wskazać, że polecenie zakończyło się pomyślnie.

Aktualizowanie logiki stanu polecenia

Delegat updateState to miejsce, w którym jest określany stan polecenia. Ten parametr jest definiowany jako Func<UpdateCommandStateContext, ResourceCommandState>. UpdateCommandStateContext udostępnia następujące właściwości:

  • UpdateCommandStateContext.ServiceProvider: wystąpienie IServiceProvider używane do rozwiązywania usług.
  • UpdateCommandStateContext.ResourceSnapshot: migawka wystąpienia zasobu, na podstawie którego jest wykonywane polecenie.

Niezmienna migawka to wystąpienie CustomResourceSnapshot, które uwidacznia wszelkiego rodzaju cenne szczegóły dotyczące wystąpienia zasobu. Rozważ następujący kod:

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;
}

Powyższy kod:

  • Pobiera wystąpienie rejestratora z dostawcy usług.
  • Rejestruje szczegóły migawki zasobu.
  • Zwraca ResourceCommandState.Enabled, jeśli zasób jest w dobrej kondycji; w przeciwnym razie zwraca ResourceCommandState.Disabled.

Przetestuj polecenie niestandardowe

Aby przetestować polecenie niestandardowe, zaktualizuj plik Program.cs projektu hosta aplikacji, aby uwzględnić następujący kod:

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

Poprzedni kod wywołuje metodę rozszerzenia WithClearCommand, aby dodać polecenie niestandardowe do zasobu Redis. Uruchom aplikację i przejdź do pulpitu nawigacyjnego .NET.NET Aspire. W obszarze zasobu Redis powinno zostać wyświetlone polecenie niestandardowe. Na stronie Zasoby pulpitu nawigacyjnego wybierz przycisk wielokropka w kolumnie Akcje:

.NET Aspire pulpit nawigacyjny: Redis zasób pamięci podręcznej z wyświetlonym poleceniem niestandardowym.

Na poprzedniej ilustracji przedstawiono polecenie Wyczyść pamięć podręczną, które zostało dodane do zasobu Redis. Ikona wyświetla się jako przekreślony królik, aby wskazać, że szybkość zasobu zależnego jest czyszczona.

Wybierz polecenie Wyczyść pamięć podręczną, aby wyczyścić pamięć podręczną zasobu Redis. Polecenie powinno zostać wykonane pomyślnie, a pamięć podręczna powinna zostać wyczyszczona.

pulpit nawigacyjny .NET Aspire: Redis zasób pamięci podręcznej z wykonanym poleceniem niestandardowym.

Zobacz też