using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using System.Net.Http; namespace ReC.Client { /// /// Static convenience entry-point for building and resolving a without an /// externally provided . Intended for legacy scenarios (e.g. .NET Framework /// codebases without an established DI container). For new code, prefer /// . /// public partial class ReCClient { #if NET8_0_OR_GREATER private static Action? _staticConfigure = null; #else private static Action _staticConfigure = null; #endif private static readonly Lazy LazyProvider = new Lazy(() => { var configure = _staticConfigure ?? throw new InvalidOperationException("Static Provider is not built. Call BuildStaticClient first."); var services = new ServiceCollection(); configure(services); 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. /// /// /// This method should only be called once during application startup. /// The underlying is created lazily and thread-safely on first access via . /// /// 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 BuildStaticClient(Action) instead.")] #if NETFRAMEWORK public static void BuildStaticClient(string apiUri, Action configureOptions = null, ILogger logger = null) #else public static void BuildStaticClient(string apiUri, Action? configureOptions = null, ILogger? logger = null) #endif { BuildStaticClient(cfg => { cfg.BaseAddress = apiUri; cfg.ConfigureOptions = configureOptions; cfg.Logger = logger; }); } /// /// 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 . /// /// 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 BuildStaticClient(Action) instead.")] #if NETFRAMEWORK public static void BuildStaticClient(Action configureClient, Action configureOptions = null, ILogger logger = null) #else public static void BuildStaticClient(Action configureClient, Action? configureOptions = null, ILogger? logger = null) #endif { BuildStaticClient(cfg => { cfg.ConfigureClient = configureClient; cfg.ConfigureOptions = configureOptions; cfg.Logger = logger; }); } /// /// Creates a new instance using the statically configured provider. /// /// A new instance of the . /// Thrown if has not been called yet. [Obsolete("Use a local service collection instead of the static provider.")] public static ReCClient Create() { return LazyProvider.Value.GetRequiredService(); } } }