using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using ReC.Application.Common.Behaviors; using ReC.Application.Common.Options; using System.Reflection; namespace ReC.Application; public static class DependencyInjection { public static IServiceCollection AddRecServices(this IServiceCollection services, Action options) { var configOpt = new ConfigurationOptions(); options.Invoke(configOpt); configOpt.EnsureRequiredServices(); configOpt.ApplyConfigurations(services); services.AddAutoMapper(cfg => { cfg.AddMaps(Assembly.GetExecutingAssembly()); cfg.LicenseKey = configOpt.LuckyPennySoftwareLicenseKey; }); services.AddMediatR(cfg => { cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()); cfg.AddOpenBehaviors([typeof(BodyQueryBehavior<>), typeof(HeaderQueryBehavior<>)]); cfg.LicenseKey = configOpt.LuckyPennySoftwareLicenseKey; }); services.AddHttpClient(); return services; } public class ConfigurationOptions { #region Required Services private readonly Dictionary _requiredServices = new() { { nameof(ConfigureRecActions), false }, { nameof(LuckyPennySoftwareLicenseKey), false } }; internal void EnsureRequiredServices() { var missingServices = _requiredServices .Where(kvp => !kvp.Value) .Select(kvp => kvp.Key.Replace("Configure", string.Empty)); if (missingServices.Any()) throw new InvalidOperationException($"The following required services were not configured: {string.Join(", ", missingServices)}"); } #endregion Required Services #region Configuration private readonly Queue> _configActions = new(); internal void ApplyConfigurations(IServiceCollection services) { while (_configActions.Count > 0) { var action = _configActions.Dequeue(); action(services); } } #endregion Configuration #region LuckyPennySoftwareLicenseKey private string? _luckyPennySoftwareLicenseKey; public string? LuckyPennySoftwareLicenseKey { get => _luckyPennySoftwareLicenseKey; set { _luckyPennySoftwareLicenseKey = value; if (value is not null) _requiredServices[nameof(LuckyPennySoftwareLicenseKey)] = true; } } #endregion LuckyPennySoftwareLicenseKey #region ConfigureRecActions public ConfigurationOptions ConfigureRecActions(Action configure) { _configActions.Enqueue(services => services.Configure(configure)); if(_requiredServices[nameof(ConfigureRecActions)]) throw new InvalidOperationException("RecActionOptions have already been configured."); _requiredServices[nameof(ConfigureRecActions)] = true; return this; } public ConfigurationOptions ConfigureRecActions(IConfiguration configuration) { _configActions.Enqueue(services => services.Configure(configuration)); if (_requiredServices[nameof(ConfigureRecActions)]) throw new InvalidOperationException("RecActionOptions have already been configured."); _requiredServices[nameof(ConfigureRecActions)] = true; return this; } #endregion ConfigureRecActions } }