using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using NPin.Framework.SettingManagement.Domain.Options; using NPin.Framework.SettingManagement.Domain.Provider; using Volo.Abp.DependencyInjection; using Volo.Abp.Settings; namespace NPin.Framework.SettingManagement.Domain; public class SettingManager : ISettingManager, ISingletonDependency { private readonly Lazy> _lazyProviders; protected readonly IServiceProvider ServiceProvider; protected ISettingDefinitionManager SettingDefinitionManager { get; } protected ISettingEncryptionService SettingEncryptionService { get; } protected List Providers => _lazyProviders.Value; protected SettingManagementOptions Options { get; } public SettingManager( IServiceProvider serviceProvider, ISettingDefinitionManager settingDefinitionManager, ISettingEncryptionService settingEncryptionService, IOptions options) { ServiceProvider = serviceProvider; SettingDefinitionManager = settingDefinitionManager; SettingEncryptionService = settingEncryptionService; Options = options.Value; _lazyProviders = new Lazy>(CreateSettingManagementProviders, true); } protected virtual List CreateSettingManagementProviders() { using var scope = ServiceProvider.CreateScope(); return Options.Providers .Select(p => (scope.ServiceProvider.GetRequiredService(p) as ISettingManagementProvider)!) .ToList(); } public virtual Task GetOrNullAsync(string name, string providerName, string? providerKey, bool fallback = true) { Check.NotNull(name, nameof(name)); Check.NotNull(providerName, nameof(providerName)); return GetOrNullInternalAsync(name, providerName, providerKey, fallback); } public virtual async Task> GetAllAsync(string providerName, string? providerKey, bool fallback = true) { Check.NotNull(providerName, nameof(providerName)); var settingDefinitions = await SettingDefinitionManager.GetAllAsync(); var providers = Enumerable.Reverse(Providers) .SkipWhile(c => c.Name != providerName); if (!fallback) { providers = providers.TakeWhile(c => c.Name == providerName); } var providerList = providers.Reverse().ToList(); if (!providerList.Any()) { return new List(); } var settingValues = new Dictionary(); foreach (var setting in settingDefinitions) { string value = null; if (setting.IsInherited) { foreach (var provider in providerList) { var providerValue = await provider.GetOrNullAsync( setting, provider.Name == providerName ? providerKey : null ); if (providerValue != null) { value = providerValue; } } } else { value = await providerList[0].GetOrNullAsync( setting, providerKey ); } if (setting.IsEncrypted) { value = SettingEncryptionService.Decrypt(setting, value); } if (value != null) { settingValues[setting.Name] = new SettingValue(setting.Name, value); } } return settingValues.Values.ToList(); } public virtual async Task SetAsync(string name, string? value, string providerName, string? providerKey, bool forceToSet = false) { Check.NotNull(name, nameof(name)); Check.NotNull(providerName, nameof(providerName)); var setting = await SettingDefinitionManager.GetAsync(name); var providers = Enumerable .Reverse(Providers) .SkipWhile(p => p.Name != providerName) .ToList(); if (!providers.Any()) { return; } if (setting.IsEncrypted) { value = SettingEncryptionService.Encrypt(setting, value); } if (providers.Count > 1 && !forceToSet && setting.IsInherited && value != null) { var fallbackValue = await GetOrNullInternalAsync(name, providers[1].Name, null); if (fallbackValue == value) { //Clear the value if it's same as it's fallback value value = null; } } providers = providers .TakeWhile(p => p.Name == providerName) .ToList(); //Getting list for case of there are more than one provider with same providerName if (value == null) { foreach (var provider in providers) { await provider.ClearAsync(setting, providerKey); } } else { foreach (var provider in providers) { await provider.SetAsync(setting, value, providerKey); } } } protected virtual async Task GetOrNullInternalAsync(string name, string? providerName, string? providerKey, bool fallback = true) { var setting = await SettingDefinitionManager.GetAsync(name); var providers = Enumerable .Reverse(Providers); if (providerName != null) { providers = providers.SkipWhile(c => c.Name != providerName); } if (!fallback || !setting.IsInherited) { providers = providers.TakeWhile(c => c.Name == providerName); } string value = null; foreach (var provider in providers) { value = await provider.GetOrNullAsync( setting, provider.Name == providerName ? providerKey : null ); if (value != null) { break; } } if (setting.IsEncrypted) { value = SettingEncryptionService.Decrypt(setting, value); } return value; } }