diff --git a/src/OrchardCore/OrchardCore.Abstractions/Shell/Configuration/ShellConfiguration.cs b/src/OrchardCore/OrchardCore.Abstractions/Shell/Configuration/ShellConfiguration.cs index 3633681f74e..1d3767f76be 100644 --- a/src/OrchardCore/OrchardCore.Abstractions/Shell/Configuration/ShellConfiguration.cs +++ b/src/OrchardCore/OrchardCore.Abstractions/Shell/Configuration/ShellConfiguration.cs @@ -20,7 +20,7 @@ public class ShellConfiguration : IShellConfiguration private UpdatableDataProvider _updatableData; private readonly string _name; - private readonly Func> _configBuilderFactory; + private readonly Func, Task> _factoryAsync; private readonly SemaphoreSlim _semaphore = new(1); private bool _released; @@ -28,12 +28,6 @@ public ShellConfiguration() { } - public ShellConfiguration(IConfigurationBuilder builder) - { - _updatableData = new UpdatableDataProvider(); - _configuration = builder.Add(_updatableData).Build(); - } - public ShellConfiguration(IConfiguration configuration) { _updatableData = new UpdatableDataProvider(); @@ -44,10 +38,16 @@ public ShellConfiguration(IConfiguration configuration) .Build(); } - public ShellConfiguration(string name, Func> factory) + public ShellConfiguration(IConfigurationBuilder builder) + { + _updatableData = new UpdatableDataProvider(); + _configuration = builder.Add(_updatableData).Build(); + } + + public ShellConfiguration(string name, Func, Task> factoryAsync) { _name = name; - _configBuilderFactory = factory; + _factoryAsync = factoryAsync; } public ShellConfiguration(ShellConfiguration configuration) : this(null, configuration) @@ -75,7 +75,7 @@ public ShellConfiguration(string name, ShellConfiguration configuration) return; } - _configBuilderFactory = configuration._configBuilderFactory; + _factoryAsync = configuration._factoryAsync; } private void EnsureConfiguration() @@ -103,12 +103,11 @@ internal async Task EnsureConfigurationAsync() return; } - var builder = _configBuilderFactory is not null ? - await _configBuilderFactory.Invoke(_name) - : new ConfigurationBuilder(); - _updatableData = new UpdatableDataProvider(); - _configuration = builder.Add(_updatableData).Build(); + + _configuration = _factoryAsync is not null + ? await _factoryAsync(_name, builder => builder.Add(_updatableData)) + : new ConfigurationBuilder().Add(_updatableData).Build(); } finally { diff --git a/src/OrchardCore/OrchardCore/Shell/ShellSettingsManager.cs b/src/OrchardCore/OrchardCore/Shell/ShellSettingsManager.cs index 1673a0339a7..219215a5270 100644 --- a/src/OrchardCore/OrchardCore/Shell/ShellSettingsManager.cs +++ b/src/OrchardCore/OrchardCore/Shell/ShellSettingsManager.cs @@ -12,30 +12,33 @@ namespace OrchardCore.Environment.Shell { - public class ShellSettingsManager : IShellSettingsManager + public class ShellSettingsManager : IShellSettingsManager, IDisposable { private readonly IConfiguration _applicationConfiguration; private readonly IShellsConfigurationSources _tenantsConfigSources; private readonly IShellConfigurationSources _tenantConfigSources; - private readonly IShellsSettingsSources _settingsSources; + private readonly IShellsSettingsSources _tenantsSettingsSources; private IConfiguration _configuration; + private IConfigurationRoot _configurationRoot; + private IConfigurationRoot _tenantsSettingsRoot; private IEnumerable _configuredTenants; private readonly SemaphoreSlim _semaphore = new(1); - private Func> _tenantConfigBuilderFactory; + private Func, Task> _tenantConfigFactoryAsync; private readonly SemaphoreSlim _tenantConfigSemaphore = new(1); + private bool _disposed; public ShellSettingsManager( IConfiguration applicationConfiguration, IShellsConfigurationSources tenantsConfigSources, IShellConfigurationSources tenantConfigSources, - IShellsSettingsSources settingsSources) + IShellsSettingsSources tenantsSettingsSources) { _applicationConfiguration = applicationConfiguration; _tenantsConfigSources = tenantsConfigSources; _tenantConfigSources = tenantConfigSources; - _settingsSources = settingsSources; + _tenantsSettingsSources = tenantsSettingsSources; } public ShellSettings CreateDefaultSettings() @@ -54,26 +57,20 @@ public async Task> LoadSettingsAsync() { await EnsureConfigurationAsync(); - var tenantsSettings = (await new ConfigurationBuilder() - .AddSourcesAsync(_settingsSources)) - .Build(); - - using var disposable = tenantsSettings as IDisposable; - - var tenants = tenantsSettings.GetChildren().Select(section => section.Key); + var tenants = _tenantsSettingsRoot.GetChildren().Select(section => section.Key); var allTenants = _configuredTenants.Concat(tenants).Distinct().ToArray(); var allSettings = new List(); foreach (var tenant in allTenants) { - var tenantSettings = new ConfigurationBuilder() + var tenantSettingsBuilder = new ConfigurationBuilder() .AddConfiguration(_configuration) .AddConfiguration(_configuration.GetSection(tenant)) - .AddConfiguration(tenantsSettings.GetSection(tenant)); + .AddConfiguration(_tenantsSettingsRoot.GetSection(tenant)); - var settings = new ShellConfiguration(tenantSettings); - var configuration = new ShellConfiguration(tenant, _tenantConfigBuilderFactory); + var settings = new ShellConfiguration(tenantSettingsBuilder); + var configuration = new ShellConfiguration(tenant, _tenantConfigFactoryAsync); var shellSettings = new ShellSettings(settings, configuration) { @@ -98,13 +95,9 @@ public async Task> LoadSettingsNamesAsync() { await EnsureConfigurationAsync(); - var tenantsSettings = (await new ConfigurationBuilder() - .AddSourcesAsync(_settingsSources)) - .Build(); - - using var disposable = tenantsSettings as IDisposable; + _tenantsSettingsRoot.Reload(); - var tenants = tenantsSettings.GetChildren().Select(section => section.Key); + var tenants = _tenantsSettingsRoot.GetChildren().Select(section => section.Key); return _configuredTenants.Concat(tenants).Distinct().ToArray(); } finally @@ -120,19 +113,15 @@ public async Task LoadSettingsAsync(string tenant) { await EnsureConfigurationAsync(); - var tenantsSettings = (await new ConfigurationBuilder() - .AddSourcesAsync(tenant, _settingsSources)) - .Build(); - - using var disposable = tenantsSettings as IDisposable; + _tenantsSettingsRoot.Reload(); - var tenantSettings = new ConfigurationBuilder() + var tenantSettingsBuilder = new ConfigurationBuilder() .AddConfiguration(_configuration) .AddConfiguration(_configuration.GetSection(tenant)) - .AddConfiguration(tenantsSettings.GetSection(tenant)); + .AddConfiguration(_tenantsSettingsRoot.GetSection(tenant)); - var settings = new ShellConfiguration(tenantSettings); - var configuration = new ShellConfiguration(tenant, _tenantConfigBuilderFactory); + var settings = new ShellConfiguration(tenantSettingsBuilder); + var configuration = new ShellConfiguration(tenant, _tenantConfigFactoryAsync); return new ShellSettings(settings, configuration) { @@ -152,7 +141,7 @@ public async Task SaveSettingsAsync(ShellSettings settings) { await EnsureConfigurationAsync(); - if (settings == null) + if (settings is null) { throw new ArgumentNullException(nameof(settings)); } @@ -189,7 +178,7 @@ public async Task SaveSettingsAsync(ShellSettings settings) tenantSettings.Remove("Name"); - await _settingsSources.SaveAsync(settings.Name, tenantSettings.ToObject>()); + await _tenantsSettingsSources.SaveAsync(settings.Name, tenantSettings.ToObject>()); var tenantConfig = new JObject(); @@ -234,12 +223,12 @@ public async Task RemoveSettingsAsync(ShellSettings settings) { await EnsureConfigurationAsync(); - if (settings == null) + if (settings is null) { throw new ArgumentNullException(nameof(settings)); } - await _settingsSources.RemoveAsync(settings.Name); + await _tenantsSettingsSources.RemoveAsync(settings.Name); await _tenantConfigSemaphore.WaitAsync(); try @@ -259,7 +248,7 @@ public async Task RemoveSettingsAsync(ShellSettings settings) private async Task EnsureConfigurationAsync() { - if (_configuration != null) + if (_configuration is not null) { return; } @@ -279,7 +268,8 @@ private async Task EnsureConfigurationAsync() configurationBuilder.AddConfiguration(new ConfigurationRoot(lastProviders)); } - var configuration = configurationBuilder.Build().GetSection("OrchardCore"); + _configurationRoot = configurationBuilder.Build(); + var configuration = _configurationRoot.GetSection("OrchardCore"); _configuredTenants = configuration.GetChildren() .Where(section => Enum.TryParse(section["State"], ignoreCase: true, out _)) @@ -287,15 +277,23 @@ private async Task EnsureConfigurationAsync() .Distinct() .ToArray(); - _tenantConfigBuilderFactory = async (tenant) => + _tenantsSettingsRoot = (await new ConfigurationBuilder() + .AddSourcesAsync(_tenantsSettingsSources)) + .Build(); + + _tenantConfigFactoryAsync = async (tenant, configure) => { await _tenantConfigSemaphore.WaitAsync(); try { - return await new ConfigurationBuilder() + var builder = await new ConfigurationBuilder() .AddConfiguration(_configuration) .AddConfiguration(_configuration.GetSection(tenant)) .AddSourcesAsync(tenant, _tenantConfigSources); + + configure(builder); + + return builder.Build(); } finally { @@ -305,5 +303,23 @@ private async Task EnsureConfigurationAsync() _configuration = configuration; } + + public void Dispose() + { + if (_disposed) + { + return; + } + + _disposed = true; + + (_configurationRoot as IDisposable)?.Dispose(); + (_tenantsSettingsRoot as IDisposable)?.Dispose(); + + _semaphore?.Dispose(); + _tenantConfigSemaphore?.Dispose(); + + GC.SuppressFinalize(this); + } } }