diff --git a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs index 2ce4bb030..1dec341fd 100644 --- a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs +++ b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs @@ -20,21 +20,17 @@ using static Elsa.Api.Client.RefitSettingsHelper; namespace Elsa.Api.Client.Extensions; -/// /// Provides extension methods for dependency injection. -/// [PublicAPI] public static class DependencyInjectionExtensions { - /// - /// Adds the Elsa API client configured to use an API key to the service collection. - /// - public static IServiceCollection AddElsaApiKeyClient(this IServiceCollection services, Action configureOptions) + /// Adds default Elsa API clients configured to use an API key. + public static IServiceCollection AddDefaultApiClientsUsingApiKey(this IServiceCollection services, Action configureOptions) { var options = new ElsaClientOptions(); configureOptions(options); - return services.AddElsaClient(client => + return services.AddDefaultApiClients(client => { client.BaseAddress = options.BaseAddress; client.ApiKey = options.ApiKey; @@ -42,49 +38,70 @@ public static class DependencyInjectionExtensions }); } - /// - /// Adds the Elsa client to the service collection. - /// - public static IServiceCollection AddElsaClient(this IServiceCollection services, Action configureClient) + /// Adds default Elsa API clients. + public static IServiceCollection AddDefaultApiClients(this IServiceCollection services, Action configureClient) { - var builderOptions = new ElsaClientBuilderOptions(); - configureClient.Invoke(builderOptions); - builderOptions.ConfigureHttpClientBuilder += builder => builder.AddHttpMessageHandler(sp => (DelegatingHandler)sp.GetRequiredService(builderOptions.AuthenticationHandler)); - - services.AddScoped(builderOptions.AuthenticationHandler); - - services.Configure(options => + return services.AddApiClients(configureClient, builderOptions => { - options.BaseAddress = builderOptions.BaseAddress; - options.ConfigureHttpClient = builderOptions.ConfigureHttpClient; - options.ApiKey = builderOptions.ApiKey; + var builderOptionsWithoutRetryPolicy = new ElsaClientBuilderOptions + { + ApiKey = builderOptions.ApiKey, + AuthenticationHandler = builderOptions.AuthenticationHandler, + BaseAddress = builderOptions.BaseAddress, + ConfigureHttpClient = builderOptions.ConfigureHttpClient, + ConfigureHttpClientBuilder = builderOptions.ConfigureHttpClientBuilder, + ConfigureRetryPolicy = null + }; + + services.AddApi(builderOptions); + services.AddApi(builderOptionsWithoutRetryPolicy); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); + services.AddApi(builderOptions); }); + } - var builderOptionsWithoutRetryPolicy = new ElsaClientBuilderOptions + /// + /// Adds an API client to the service collection. Requires AddElsaClient to be called exactly once. + /// + public static IServiceCollection AddApiClient(this IServiceCollection services, Action configureClient) where T : class + { + return services.AddApiClients(configureClient, builderOptions => services.AddApi(builderOptions)); + } + + /// Adds the Elsa client to the service collection. + public static IServiceCollection AddApiClients(this IServiceCollection services, Action configureClient, Action? configureServices) + { + var builderOptionsServiceDescriptor = services.FirstOrDefault(x => x.ServiceType == typeof(ElsaClientBuilderOptions)); + + if (builderOptionsServiceDescriptor == null) { - ApiKey = builderOptions.ApiKey, - AuthenticationHandler = builderOptions.AuthenticationHandler, - BaseAddress = builderOptions.BaseAddress, - ConfigureHttpClient = builderOptions.ConfigureHttpClient, - ConfigureHttpClientBuilder = builderOptions.ConfigureHttpClientBuilder, - ConfigureRetryPolicy = null - }; + var builderOptions = new ElsaClientBuilderOptions(); + configureClient.Invoke(builderOptions); + builderOptions.ConfigureHttpClientBuilder += builder => builder.AddHttpMessageHandler(sp => (DelegatingHandler)sp.GetRequiredService(builderOptions.AuthenticationHandler)); + + services.AddScoped(builderOptions.AuthenticationHandler); + + services.Configure(options => + { + options.BaseAddress = builderOptions.BaseAddress; + options.ConfigureHttpClient = builderOptions.ConfigureHttpClient; + options.ApiKey = builderOptions.ApiKey; + }); + + configureServices?.Invoke(builderOptions); + } - services.AddApi(builderOptions); - services.AddApi(builderOptionsWithoutRetryPolicy); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); - services.AddApi(builderOptions); return services; } @@ -94,11 +111,23 @@ public static class DependencyInjectionExtensions /// The service collection. /// An options object that can be used to configure the HTTP client builder. /// The type representing the API. - public static void AddApi(this IServiceCollection services, ElsaClientBuilderOptions? httpClientBuilderOptions = default) where T : class + public static IServiceCollection AddApi(this IServiceCollection services, ElsaClientBuilderOptions? httpClientBuilderOptions = default) where T : class { - var builder = services.AddRefitClient(_ => CreateRefitSettings(), typeof(T).Name).ConfigureHttpClient(ConfigureElsaApiHttpClient); + return services.AddApi(typeof(T), httpClientBuilderOptions); + } + + /// + /// Adds a refit client for the specified API type. + /// + /// The service collection. + /// The type representing the API + /// An options object that can be used to configure the HTTP client builder. + public static IServiceCollection AddApi(this IServiceCollection services, Type apiType, ElsaClientBuilderOptions? httpClientBuilderOptions = default) + { + var builder = services.AddRefitClient(apiType, _ => CreateRefitSettings(), apiType.Name).ConfigureHttpClient(ConfigureElsaApiHttpClient); httpClientBuilderOptions?.ConfigureHttpClientBuilder(builder); httpClientBuilderOptions?.ConfigureRetryPolicy?.Invoke(builder); + return services; } /// @@ -115,9 +144,7 @@ public static class DependencyInjectionExtensions httpClientBuilderOptions?.ConfigureHttpClientBuilder(builder); } - /// /// Creates an API client for the specified API type. - /// public static T CreateApi(this IServiceProvider serviceProvider, Uri baseAddress) where T : class { var httpClientFactory = serviceProvider.GetRequiredService(); @@ -126,9 +153,7 @@ public static class DependencyInjectionExtensions return CreateApi(serviceProvider, httpClient); } - /// /// Creates an API client for the specified API type. - /// public static T CreateApi(this IServiceProvider serviceProvider, HttpClient httpClient) where T : class { return RestService.For(httpClient, CreateRefitSettings());