diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs
index 53acbdb132..dd0b83dcb3 100644
--- a/src/Umbraco.Core/Components/Composition.cs
+++ b/src/Umbraco.Core/Components/Composition.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Composing;
+using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Components
@@ -26,12 +27,21 @@ namespace Umbraco.Core.Components
/// A type loader.
/// A logger.
/// The runtime state.
- public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState)
+ /// Optional configs.
+ public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs = null)
{
_register = register;
TypeLoader = typeLoader;
Logger = logger;
RuntimeState = runtimeState;
+
+ if (configs == null)
+ {
+ configs = new Configs();
+ configs.AddCoreConfigs();
+ }
+
+ Configs = configs;
}
#region Services
@@ -51,6 +61,11 @@ namespace Umbraco.Core.Components
///
public IRuntimeState RuntimeState { get; }
+ ///
+ /// Gets the configurations.
+ ///
+ public Configs Configs { get; }
+
#endregion
#region IRegister
@@ -94,6 +109,8 @@ namespace Umbraco.Core.Components
foreach (var builder in _builders.Values)
builder.RegisterWith(_register);
+ Configs.RegisterWith(_register);
+
return _register.CreateFactory();
}
diff --git a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs
index 7217f551e9..ca86f623cc 100644
--- a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs
+++ b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs
@@ -5,24 +5,19 @@ using Umbraco.Core.Configuration.UmbracoSettings;
namespace Umbraco.Core.Composing.Composers
{
///
- /// Sets up IoC container for Umbraco configuration classes
+ /// Compose configurations.
///
public static class ConfigurationComposer
{
public static Composition ComposeConfiguration(this Composition composition)
{
- composition.RegisterUnique();
- composition.RegisterUnique(factory => factory.GetInstance().Umbraco());
+ // common configurations are already registered
+ // register others
+
composition.RegisterUnique(factory => factory.GetInstance().Content);
composition.RegisterUnique(factory => factory.GetInstance().Templates);
composition.RegisterUnique(factory => factory.GetInstance().RequestHandler);
composition.RegisterUnique(factory => factory.GetInstance().Security);
- composition.RegisterUnique(factory => factory.GetInstance().Global());
- composition.RegisterUnique(factory => factory.GetInstance().Dashboards());
- composition.RegisterUnique(factory => factory.GetInstance().HealthChecks());
- composition.RegisterUnique(factory => factory.GetInstance().Grids());
-
- // fixme - other sections we need to add?
return composition;
}
diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs
index 6c093dfc2c..7050f3b112 100644
--- a/src/Umbraco.Core/Composing/Current.cs
+++ b/src/Umbraco.Core/Composing/Current.cs
@@ -39,7 +39,7 @@ namespace Umbraco.Core.Composing
private static IProfiler _profiler;
private static IProfilingLogger _profilingLogger;
private static IPublishedValueFallback _publishedValueFallback;
- private static UmbracoConfig _config;
+ private static Configs _configs;
///
/// Gets or sets the factory.
@@ -48,17 +48,18 @@ namespace Umbraco.Core.Composing
{
get
{
- if (_factory == null) throw new Exception("No factory has been set.");
+ if (_factory == null) throw new InvalidOperationException("No factory has been set.");
return _factory;
}
set
{
- if (_factory != null) throw new Exception("A factory has already been set.");
+ if (_factory != null) throw new InvalidOperationException("A factory has already been set.");
+ if (_configs != null) throw new InvalidOperationException("Configs are unlocked.");
_factory = value;
}
}
- internal static bool HasContainer => _factory != null;
+ internal static bool HasFactory => _factory != null;
// for UNIT TESTS exclusively!
// resets *everything* that is 'current'
@@ -67,6 +68,7 @@ namespace Umbraco.Core.Composing
_factory.DisposeIfDisposable();
_factory = null;
+ _configs = null;
_shortStringHelper = null;
_logger = null;
_profiler = null;
@@ -76,21 +78,31 @@ namespace Umbraco.Core.Composing
Resetted?.Invoke(null, EventArgs.Empty);
}
+ // for UNIT TESTS exclusively!
+ // unlocks configuration, so it is possible to add configurations
+ // to Current.Configs - without having to use composition.Configs
+ internal static void UnlockConfigs()
+ {
+ if (_factory != null)
+ throw new InvalidOperationException("Cannot unlock configs when a factory has been set.");
+ _configs = new Configs();
+ }
+
internal static event EventHandler Resetted;
#region Getters
public static IShortStringHelper ShortStringHelper
=> _shortStringHelper ?? (_shortStringHelper = _factory?.TryGetInstance()
- ?? new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(Config.Umbraco())));
+ ?? new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(Configs.Settings())));
public static ILogger Logger
=> _logger ?? (_logger = _factory?.TryGetInstance()
- ?? new DebugDiagnosticsLogger());
+ ?? new DebugDiagnosticsLogger());
public static IProfiler Profiler
=> _profiler ?? (_profiler = _factory?.TryGetInstance()
- ?? new LogProfiler(Logger));
+ ?? new LogProfiler(Logger));
public static IProfilingLogger ProfilingLogger
=> _profilingLogger ?? (_profilingLogger = _factory?.TryGetInstance())
@@ -102,9 +114,15 @@ namespace Umbraco.Core.Composing
public static TypeLoader TypeLoader
=> Factory.GetInstance();
- public static UmbracoConfig Config
- => _config ?? (_config = _factory?.TryGetInstance()
- ?? new UmbracoConfig(Logger, _factory?.TryGetInstance(), _factory?.TryGetInstance()));
+ public static Configs Configs
+ {
+ get
+ {
+ if (_configs != null) return _configs;
+ if (_factory == null) throw new InvalidOperationException("Can not get Current.Config during composition. Use composition.Config.");
+ return _factory.GetInstance();
+ }
+ }
public static IFileSystems FileSystems
=> Factory.GetInstance();
diff --git a/src/Umbraco.Core/ConfigsExtensions.cs b/src/Umbraco.Core/ConfigsExtensions.cs
new file mode 100644
index 0000000000..1414dbc852
--- /dev/null
+++ b/src/Umbraco.Core/ConfigsExtensions.cs
@@ -0,0 +1,52 @@
+using System.IO;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.Dashboard;
+using Umbraco.Core.Configuration.Grid;
+using Umbraco.Core.Configuration.HealthChecks;
+using Umbraco.Core.Configuration.UmbracoSettings;
+using Umbraco.Core.IO;
+using Umbraco.Core.Logging;
+
+namespace Umbraco.Core
+{
+ ///
+ /// Provides extension methods for the class.
+ ///
+ public static class ConfigsExtensions
+ {
+ public static IGlobalSettings Global(this Configs configs)
+ => configs.GetConfig();
+
+ public static IUmbracoSettingsSection Settings(this Configs configs)
+ => configs.GetConfig();
+
+ public static IDashboardSection Dashboards(this Configs configs)
+ => configs.GetConfig();
+
+ public static IHealthChecks HealthChecks(this Configs configs)
+ => configs.GetConfig();
+
+ public static IGridConfig Grids(this Configs configs)
+ => configs.GetConfig();
+
+ internal static CoreDebug CoreDebug(this Configs configs)
+ => configs.GetConfig();
+
+ public static void AddCoreConfigs(this Configs configs)
+ {
+ var configDir = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config));
+
+ configs.Add(() => new GlobalSettings());
+ configs.Add("umbracoConfiguration/settings");
+ configs.Add("umbracoConfiguration/dashBoard");
+ configs.Add("umbracoConfiguration/HealthChecks");
+
+ configs.Add(() => new CoreDebug());
+
+ // GridConfig depends on runtime caches, manifest parsers... and cannot be available during composition
+ configs.Add(factory => new GridConfig(factory.GetInstance(), factory.GetInstance(), configDir, factory.GetInstance().Debug));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/Configs.cs b/src/Umbraco.Core/Configuration/Configs.cs
new file mode 100644
index 0000000000..3dbbe5d4ff
--- /dev/null
+++ b/src/Umbraco.Core/Configuration/Configs.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Logging;
+
+namespace Umbraco.Core.Configuration
+{
+ ///
+ /// Represents Umbraco configurations.
+ ///
+ ///
+ /// During composition, use composition.Configs. When running, either inject the required configuration,
+ /// or use Current.Configs.
+ ///
+ public class Configs
+ {
+ private readonly Dictionary> _configs = new Dictionary>();
+ private Dictionary> _registerings = new Dictionary>();
+
+ ///
+ /// Gets a configuration.
+ ///
+ public TConfig GetConfig()
+ where TConfig : class
+ {
+ if (!_configs.TryGetValue(typeof(TConfig), out var configFactory))
+ throw new InvalidOperationException($"No configuration of type {typeof(TConfig)} has been added.");
+
+ return (TConfig) configFactory.Value;
+ }
+
+ ///
+ /// Adds a configuration, provided by a factory.
+ ///
+ public void Add(Func configFactory)
+ where TConfig : class
+ {
+ // make sure it is not too late
+ if (_registerings == null)
+ throw new InvalidOperationException("Configurations have already been registered.");
+
+ var typeOfConfig = typeof(TConfig);
+
+ var lazyConfigFactory = _configs[typeOfConfig] = new Lazy