diff --git a/src/ReC.Client/ReCClient.cs b/src/ReC.Client/ReCClient.cs index 51aa917..fc537e9 100644 --- a/src/ReC.Client/ReCClient.cs +++ b/src/ReC.Client/ReCClient.cs @@ -101,6 +101,53 @@ namespace ReC.Client return services.BuildServiceProvider(); }, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication); + /// + /// Configures and builds the static for creating instances. + /// + /// + /// This method should only be called once during application startup. The underlying + /// is created lazily and thread-safely on first access via . + /// + /// Callback that populates a instance. + /// Thrown when is null. + /// Thrown when neither nor is set, when both are set, or when the static provider has already been built. + [Obsolete("Use a local service collection instead of the static provider.")] + public static void BuildStaticClient(Action configure) + { + if (configure == null) + throw new ArgumentNullException(nameof(configure)); + + var cfg = new StaticBuildConfiguration(); + configure(cfg); + + var hasBaseAddress = !string.IsNullOrWhiteSpace(cfg.BaseAddress); + var hasConfigureClient = cfg.ConfigureClient != null; + + if (!hasBaseAddress && !hasConfigureClient) + throw new InvalidOperationException( + $"Either {nameof(StaticBuildConfiguration.BaseAddress)} or {nameof(StaticBuildConfiguration.ConfigureClient)} must be set on {nameof(StaticBuildConfiguration)}."); + + if (hasBaseAddress && hasConfigureClient) + throw new InvalidOperationException( + $"{nameof(StaticBuildConfiguration.BaseAddress)} and {nameof(StaticBuildConfiguration.ConfigureClient)} are mutually exclusive on {nameof(StaticBuildConfiguration)}."); + + Action register = services => + { + if (hasBaseAddress) + services.AddRecClient(cfg.BaseAddress, cfg.ConfigureOptions); + else + services.AddRecClient(cfg.ConfigureClient, cfg.ConfigureOptions); + + if (cfg.Logger != null) + services.AddSingleton(cfg.Logger); + + cfg.ConfigureServices?.Invoke(services); + }; + + if (System.Threading.Interlocked.CompareExchange(ref _staticConfigure, register, null) != null) + throw new InvalidOperationException("Static Provider is already built."); + } + /// /// Configures and builds the static for creating instances. /// @@ -110,17 +157,21 @@ namespace ReC.Client /// /// The base URI of the ReC API. /// An optional callback to configure . + /// An optional instance to be used by the . When provided, it is registered as a singleton in the internal service collection. /// Thrown if the static provider has already been built. - [Obsolete("Use a local service collection instead of the static provider.")] + [Obsolete("Use BuildStaticClient(Action) instead.")] #if NETFRAMEWORK - public static void BuildStaticClient(string apiUri, Action configureOptions = null) + public static void BuildStaticClient(string apiUri, Action configureOptions = null, ILogger logger = null) #else - public static void BuildStaticClient(string apiUri, Action? configureOptions = null) + public static void BuildStaticClient(string apiUri, Action? configureOptions = null, ILogger? logger = null) #endif { - Action configure = services => services.AddRecClient(apiUri, configureOptions); - if (System.Threading.Interlocked.CompareExchange(ref _staticConfigure, configure, null) != null) - throw new InvalidOperationException("Static Provider is already built."); + BuildStaticClient(cfg => + { + cfg.BaseAddress = apiUri; + cfg.ConfigureOptions = configureOptions; + cfg.Logger = logger; + }); } /// @@ -132,17 +183,21 @@ namespace ReC.Client /// /// An action to configure the . /// An optional callback to configure . + /// An optional instance to be used by the . When provided, it is registered as a singleton in the internal service collection. /// Thrown if the static provider has already been built. - [Obsolete("Use a local service collection instead of the static provider.")] + [Obsolete("Use BuildStaticClient(Action) instead.")] #if NETFRAMEWORK - public static void BuildStaticClient(Action configureClient, Action configureOptions = null) + public static void BuildStaticClient(Action configureClient, Action configureOptions = null, ILogger logger = null) #else - public static void BuildStaticClient(Action configureClient, Action? configureOptions = null) + public static void BuildStaticClient(Action configureClient, Action? configureOptions = null, ILogger? logger = null) #endif { - Action configure = services => services.AddRecClient(configureClient, configureOptions); - if (System.Threading.Interlocked.CompareExchange(ref _staticConfigure, configure, null) != null) - throw new InvalidOperationException("Static Provider is already built."); + BuildStaticClient(cfg => + { + cfg.ConfigureClient = configureClient; + cfg.ConfigureOptions = configureOptions; + cfg.Logger = logger; + }); } /// diff --git a/src/ReC.Client/StaticBuildConfiguration.cs b/src/ReC.Client/StaticBuildConfiguration.cs new file mode 100644 index 0000000..ec898c0 --- /dev/null +++ b/src/ReC.Client/StaticBuildConfiguration.cs @@ -0,0 +1,63 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using System.Net.Http; + +namespace ReC.Client +{ + /// + /// Configuration object for . + /// Groups all optional settings for the static bootstrap path. + /// + /// + /// Either or must be set; setting both at the same time is not allowed. + /// + public class StaticBuildConfiguration + { + /// + /// Base URI of the ReC API. Mutually exclusive with . + /// +#if NETFRAMEWORK + public string BaseAddress { get; set; } +#else + public string? BaseAddress { get; set; } +#endif + + /// + /// Callback that configures the underlying . Mutually exclusive with . + /// +#if NETFRAMEWORK + public Action ConfigureClient { get; set; } +#else + public Action? ConfigureClient { get; set; } +#endif + + /// + /// Optional callback to configure . + /// +#if NETFRAMEWORK + public Action ConfigureOptions { get; set; } +#else + public Action? ConfigureOptions { get; set; } +#endif + + /// + /// Optional logger instance to be registered as a singleton in the internal service collection. + /// +#if NETFRAMEWORK + public ILogger Logger { get; set; } +#else + public ILogger? Logger { get; set; } +#endif + + /// + /// Optional callback for additional service registrations on the internal + /// (e.g. services.AddLogging(...) or custom dependencies). + /// +#if NETFRAMEWORK + public Action ConfigureServices { get; set; } +#else + public Action? ConfigureServices { get; set; } +#endif + } +}