diff --git a/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs b/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs index bb4a14c147..8bae755149 100644 --- a/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs +++ b/src/Umbraco.Core/Cache/CacheRefresherCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.Cache { public class CacheRefresherCollectionBuilder : LazyCollectionBuilderBase { - public CacheRefresherCollectionBuilder(IContainer container) - : base(container) - { } - protected override CacheRefresherCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/Components.cs similarity index 80% rename from src/Umbraco.Core/Components/BootLoader.cs rename to src/Umbraco.Core/Components/Components.cs index ff0b7ab05b..155674782e 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/Components.cs @@ -13,25 +13,26 @@ namespace Umbraco.Core.Components { // note: this class is NOT thread-safe in any ways - internal class BootLoader + internal class Components { - private readonly IContainer _container; - private readonly ProfilingLogger _proflog; - private readonly ILogger _logger; + private readonly Composition _composition; + private readonly IProfilingLogger _logger; + private readonly IEnumerable _componentTypes; private IUmbracoComponent[] _components; - private bool _booted; private const int LogThresholdMilliseconds = 100; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The application container. - public BootLoader(IContainer container) + /// The composition. + /// The component types. + /// A profiling logger. + public Components(Composition composition, IEnumerable componentTypes, IProfilingLogger logger) { - _container = container ?? throw new ArgumentNullException(nameof(container)); - _proflog = container.GetInstance(); - _logger = container.GetInstance(); + _composition = composition ?? throw new ArgumentNullException(nameof(composition)); + _componentTypes = componentTypes ?? throw new ArgumentNullException(nameof(componentTypes)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } private class EnableInfo @@ -40,44 +41,42 @@ namespace Umbraco.Core.Components public int Weight = -1; } - public void Boot(IEnumerable componentTypes, RuntimeLevel level) + public void Compose() { - if (_booted) throw new InvalidOperationException("Can not boot, has already booted."); - - var orderedComponentTypes = PrepareComponentTypes(componentTypes, level); + var orderedComponentTypes = PrepareComponentTypes(); InstantiateComponents(orderedComponentTypes); - ComposeComponents(level); + ComposeComponents(); + } - using (var scope = _container.GetInstance().CreateScope()) + public void Initialize() + { + using (var scope = _composition.Container.GetInstance().CreateScope()) { InitializeComponents(); scope.Complete(); } - - // rejoice! - _booted = true; } - private IEnumerable PrepareComponentTypes(IEnumerable componentTypes, RuntimeLevel level) + private IEnumerable PrepareComponentTypes() { - using (_proflog.DebugDuration("Preparing component types.", "Prepared component types.")) + using (_logger.DebugDuration("Preparing component types.", "Prepared component types.")) { - return PrepareComponentTypes2(componentTypes, level); + return PrepareComponentTypes2(); } } - private IEnumerable PrepareComponentTypes2(IEnumerable componentTypes, RuntimeLevel level) + private IEnumerable PrepareComponentTypes2() { // create a list, remove those that cannot be enabled due to runtime level - var componentTypeList = componentTypes + var componentTypeList = _componentTypes .Where(x => { // use the min level specified by the attribute if any // otherwise, user components have Run min level, anything else is Unknown (always run) var attr = x.GetCustomAttribute(); var minLevel = attr?.MinLevel ?? (x.Implements() ? RuntimeLevel.Run : RuntimeLevel.Unknown); - return level >= minLevel; + return _composition.RuntimeLevel >= minLevel; }) .ToList(); @@ -107,15 +106,15 @@ namespace Umbraco.Core.Components catch (Exception e) { // in case of an error, force-dump everything to log - _logger.Info("Component Report:\r\n{ComponentReport}", GetComponentsReport(requirements)); - _logger.Error(e, "Failed to sort components."); + _logger.Info("Component Report:\r\n{ComponentReport}", GetComponentsReport(requirements)); + _logger.Error(e, "Failed to sort components."); throw; } // bit verbose but should help for troubleshooting var text = "Ordered Components: " + Environment.NewLine + string.Join(Environment.NewLine, sortedComponentTypes) + Environment.NewLine; Console.WriteLine(text); - _logger.Debug("Ordered Components: {SortedComponentTypes}", sortedComponentTypes); + _logger.Debug("Ordered Components: {SortedComponentTypes}", sortedComponentTypes); return sortedComponentTypes; } @@ -275,23 +274,23 @@ namespace Umbraco.Core.Components private void InstantiateComponents(IEnumerable types) { - using (_proflog.DebugDuration("Instantiating components.", "Instantiated components.")) + using (_logger.DebugDuration("Instantiating components.", "Instantiated components.")) { + // fixme is there a faster way? _components = types.Select(x => (IUmbracoComponent) Activator.CreateInstance(x)).ToArray(); } } - private void ComposeComponents(RuntimeLevel level) + private void ComposeComponents() { - using (_proflog.DebugDuration($"Composing components. (log when >{LogThresholdMilliseconds}ms)", "Composed components.")) + using (_logger.DebugDuration($"Composing components. (log when >{LogThresholdMilliseconds}ms)", "Composed components.")) { - var composition = new Composition(_container, level); foreach (var component in _components) { var componentType = component.GetType(); - using (_proflog.DebugDuration($"Composing {componentType.FullName}.", $"Composed {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) + using (_logger.DebugDuration($"Composing {componentType.FullName}.", $"Composed {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) { - component.Compose(composition); + component.Compose(_composition); } } } @@ -301,15 +300,15 @@ namespace Umbraco.Core.Components { // use a container scope to ensure that PerScope instances are disposed // components that require instances that should not survive should register them with PerScope lifetime - using (_proflog.DebugDuration($"Initializing components. (log when >{LogThresholdMilliseconds}ms)", "Initialized components.")) - using (_container.BeginScope()) + using (_logger.DebugDuration($"Initializing components. (log when >{LogThresholdMilliseconds}ms)", "Initialized components.")) + using (_composition.Container.BeginScope()) { foreach (var component in _components) { var componentType = component.GetType(); var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(x => x.Name == "Initialize" && x.IsGenericMethod == false && x.IsStatic == false); - using (_proflog.DebugDuration($"Initializing {componentType.FullName}.", $"Initialized {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) + using (_logger.DebugDuration($"Initializing {componentType.FullName}.", $"Initialized {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) { foreach (var initializer in initializers) { @@ -329,7 +328,7 @@ namespace Umbraco.Core.Components try { - param = _container.TryGetInstance(parameterType); + param = _composition.Container.TryGetInstance(parameterType); } catch (Exception e) { @@ -342,19 +341,13 @@ namespace Umbraco.Core.Components public void Terminate() { - if (_booted == false) - { - _proflog.Logger.Warn("Cannot terminate, has not booted."); - return; - } - - using (_proflog.DebugDuration($"Terminating. (log components when >{LogThresholdMilliseconds}ms)", "Terminated.")) + using (_logger.DebugDuration($"Terminating. (log components when >{LogThresholdMilliseconds}ms)", "Terminated.")) { for (var i = _components.Length - 1; i >= 0; i--) // terminate components in reverse order { var component = _components[i]; var componentType = component.GetType(); - using (_proflog.DebugDuration($"Terminating {componentType.FullName}.", $"Terminated {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) + using (_logger.DebugDuration($"Terminating {componentType.FullName}.", $"Terminated {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds)) { component.Terminate(); } diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 91fa519694..bf3ff40c79 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Composing; +using System; +using System.Collections.Generic; +using Umbraco.Core.Composing; namespace Umbraco.Core.Components { @@ -12,6 +14,8 @@ namespace Umbraco.Core.Components /// may cause issues. public class Composition { + private readonly Dictionary _builders = new Dictionary(); + /// /// Initializes a new instance of the class. /// @@ -33,5 +37,26 @@ namespace Umbraco.Core.Components /// Gets the runtime level. /// public RuntimeLevel RuntimeLevel { get; } + + /// + /// Gets a collection builder (and registers the collection). + /// + /// The type of the collection builder. + /// The collection builder. + public TBuilder GetCollectionBuilder() + where TBuilder: ICollectionBuilder, new() + { + var typeOfBuilder = typeof(TBuilder); + + if (_builders.TryGetValue(typeOfBuilder, out var o)) + return (TBuilder) o; + + var builder = new TBuilder(); + builder.Initialize(Container); + + _builders[typeOfBuilder] = builder; + + return builder; + } } } diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index 36c6879a32..b1d43d101c 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -16,25 +16,12 @@ namespace Umbraco.Core.Composing { private readonly List _types = new List(); private readonly object _locker = new object(); - private Func, TCollection> _collectionCtor; private Type[] _registeredTypes; - /// - /// Initializes a new instance of the - /// class with a service container. - /// - /// A container. - protected CollectionBuilderBase(IContainer container) - { - Container = container; - // ReSharper disable once DoNotCallOverridableMethodsInConstructor - Initialize(); - } - /// /// Gets the container. /// - protected IContainer Container { get; } + protected IContainer Container { get; private set; } /// /// Gets the internal list of types as an IEnumerable (immutable). @@ -44,17 +31,13 @@ namespace Umbraco.Core.Composing /// /// Initializes a new instance of the builder. /// - /// This is called by the constructor and, by default, registers the - /// collection automatically. - protected virtual void Initialize() + /// By default, this registers the collection automatically. + public virtual void Initialize(IContainer container) { - // compile the auto-collection constructor - // can be null, if no ctor found, and then assume CreateCollection has been overriden - _collectionCtor = ReflectionUtilities.EmitConstructor, TCollection>>(mustExist: false); + if (Container != null) + throw new InvalidOperationException("This builder has already been initialized."); - // we just don't want to support re-registering collections here - if (Container.GetRegistered().Any()) - throw new InvalidOperationException("Collection builders cannot be registered once the collection itself has been registered."); + Container = container; // register the collection Container.Register(_ => CreateCollection(), CollectionLifetime); @@ -131,8 +114,7 @@ namespace Umbraco.Core.Composing /// Creates a new collection each time it is invoked. public virtual TCollection CreateCollection() { - if (_collectionCtor == null) throw new InvalidOperationException("Collection auto-creation is not possible."); - return _collectionCtor(CreateItems()); + return Container.CreateInstance(CreateItems()); } protected Type EnsureType(Type type, string action) diff --git a/src/Umbraco.Core/Composing/ContainerExtensions.cs b/src/Umbraco.Core/Composing/ContainerExtensions.cs index a2eb3af7cf..789cdf6366 100644 --- a/src/Umbraco.Core/Composing/ContainerExtensions.cs +++ b/src/Umbraco.Core/Composing/ContainerExtensions.cs @@ -97,26 +97,6 @@ namespace Umbraco.Core.Composing public static void RegisterAuto(this IContainer container) => container.RegisterAuto(typeof(TServiceBase)); - /// - /// Registers and instantiates a collection builder. - /// - /// The type of the collection builder. - /// A collection builder of the specified type. - public static TBuilder RegisterCollectionBuilder(this IContainer container) - { - // make sure it's not already registered - // we just don't want to support re-registering collection builders - if (container.GetRegistered().Any()) - throw new InvalidOperationException("Collection builders should be registered only once."); - - // register the builder - // use a factory so we don't have to self-register the container - container.RegisterSingleton(factory => factory.CreateInstance(container)); - - // initialize and return the builder - return container.GetInstance(); - } - /// /// Creates an instance of a service, with arguments. /// diff --git a/src/Umbraco.Core/Composing/ICollectionBuilder.cs b/src/Umbraco.Core/Composing/ICollectionBuilder.cs index 5efc03c9ac..a493d90a0a 100644 --- a/src/Umbraco.Core/Composing/ICollectionBuilder.cs +++ b/src/Umbraco.Core/Composing/ICollectionBuilder.cs @@ -1,11 +1,22 @@ namespace Umbraco.Core.Composing { + /// + /// Represents a collection builder. + /// + public interface ICollectionBuilder + { + /// + /// Initializes a new instance of the builder, and registers the collection. + /// + void Initialize(IContainer container); + } + /// /// Represents a collection builder. /// /// The type of the collection. /// The type of the items. - public interface ICollectionBuilder + public interface ICollectionBuilder : ICollectionBuilder where TCollection : IBuilderCollection { /// diff --git a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs index 04110b2070..79e5ffd4b1 100644 --- a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs @@ -18,19 +18,12 @@ namespace Umbraco.Core.Composing private readonly List>> _producers2 = new List>>(); private readonly List _excluded = new List(); - /// - /// Initializes a new instance of the class. - /// - protected LazyCollectionBuilderBase(IContainer container) - : base(container) - { } - protected abstract TBuilder This { get; } /// /// Clears all types in the collection. /// - /// The buidler. + /// The builder. public TBuilder Clear() { Configure(types => diff --git a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs index 6dd6945ee1..5acf716ec0 100644 --- a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs @@ -13,20 +13,12 @@ namespace Umbraco.Core.Composing where TBuilder : OrderedCollectionBuilderBase where TCollection : IBuilderCollection { - /// - /// Initializes a new instance of the class. - /// - /// - protected OrderedCollectionBuilderBase(IContainer container) - : base (container) - { } - protected abstract TBuilder This { get; } /// /// Clears all types in the collection. /// - /// The buidler. + /// The builder. public TBuilder Clear() { Configure(types => types.Clear()); diff --git a/src/Umbraco.Core/Composing/TypeLoader.cs b/src/Umbraco.Core/Composing/TypeLoader.cs index 304638e017..4240f96a5b 100644 --- a/src/Umbraco.Core/Composing/TypeLoader.cs +++ b/src/Umbraco.Core/Composing/TypeLoader.cs @@ -16,7 +16,7 @@ using File = System.IO.File; namespace Umbraco.Core.Composing { /// - /// Provides methods to find and instanciate types. + /// Provides methods to find and instantiate types. /// /// /// This class should be used to get all types, the class should never be used directly. @@ -30,7 +30,7 @@ namespace Umbraco.Core.Composing private readonly IRuntimeCacheProvider _runtimeCache; private readonly IGlobalSettings _globalSettings; - private readonly ProfilingLogger _logger; + private readonly IProfilingLogger _logger; private readonly object _typesLock = new object(); private readonly Dictionary _types = new Dictionary(); @@ -49,7 +49,7 @@ namespace Umbraco.Core.Composing /// /// A profiling logger. /// Whether to detect changes using hashes. - internal TypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, ProfilingLogger logger, bool detectChanges = true) + internal TypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger, bool detectChanges = true) { _runtimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache)); _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); @@ -192,7 +192,7 @@ namespace Umbraco.Core.Composing /// The hash. /// Each file is a tuple containing the FileInfo object and a boolean which indicates whether to hash the /// file properties (false) or the file contents (true). - private static string GetFileHash(IEnumerable> filesAndFolders, ProfilingLogger logger) + private static string GetFileHash(IEnumerable> filesAndFolders, IProfilingLogger logger) { using (logger.TraceDuration("Determining hash of code files on disk", "Hash determined")) { @@ -494,7 +494,7 @@ namespace Umbraco.Core.Composing if (--attempts == 0) throw; - _logger.Logger.Debug("Attempted to get filestream for file {Path} failed, {NumberOfAttempts} attempts left, pausing for {PauseMilliseconds} milliseconds", path, attempts, pauseMilliseconds); + _logger.Debug("Attempted to get filestream for file {Path} failed, {NumberOfAttempts} attempts left, pausing for {PauseMilliseconds} milliseconds", path, attempts, pauseMilliseconds); Thread.Sleep(pauseMilliseconds); } } @@ -645,7 +645,7 @@ namespace Umbraco.Core.Composing if (typeList != null) { // need to put some logging here to try to figure out why this is happening: http://issues.umbraco.org/issue/U4-3505 - _logger.Logger.Debug("Getting {TypeName}: found a cached type list.", GetName(baseType, attributeType)); + _logger.Debug("Getting {TypeName}: found a cached type list.", GetName(baseType, attributeType)); return typeList.Types; } @@ -661,7 +661,7 @@ namespace Umbraco.Core.Composing // report (only once) and scan and update the cache file if (_reportedChange == false) { - _logger.Logger.Debug("Assemblies changes detected, need to rescan everything."); + _logger.Debug("Assemblies changes detected, need to rescan everything."); _reportedChange = true; } } @@ -676,7 +676,7 @@ namespace Umbraco.Core.Composing // so in this instance there will never be a result. if (cacheResult.Exception is CachedTypeNotFoundInFileException || cacheResult.Success == false) { - _logger.Logger.Debug("Getting {TypeName}: failed to load from cache file, must scan assemblies.", GetName(baseType, attributeType)); + _logger.Debug("Getting {TypeName}: failed to load from cache file, must scan assemblies.", GetName(baseType, attributeType)); scan = true; } else @@ -695,7 +695,7 @@ namespace Umbraco.Core.Composing catch (Exception ex) { // in case of any exception, we have to exit, and revert to scanning - _logger.Logger.Error(ex, "Getting {TypeName}: failed to load cache file type {CacheType}, reverting to scanning assemblies.", GetName(baseType, attributeType), type); + _logger.Error(ex, "Getting {TypeName}: failed to load cache file type {CacheType}, reverting to scanning assemblies.", GetName(baseType, attributeType), type); scan = true; break; } @@ -703,7 +703,7 @@ namespace Umbraco.Core.Composing if (scan == false) { - _logger.Logger.Debug("Getting {TypeName}: loaded types from cache file.", GetName(baseType, attributeType)); + _logger.Debug("Getting {TypeName}: loaded types from cache file.", GetName(baseType, attributeType)); } } } @@ -711,7 +711,7 @@ namespace Umbraco.Core.Composing if (scan) { // either we had to scan, or we could not get the types from the cache file - scan now - _logger.Logger.Debug("Getting {TypeName}: scanning assemblies.", GetName(baseType, attributeType)); + _logger.Debug("Getting {TypeName}: scanning assemblies.", GetName(baseType, attributeType)); foreach (var t in finder()) typeList.Add(t); @@ -729,11 +729,11 @@ namespace Umbraco.Core.Composing UpdateCache(); } - _logger.Logger.Debug("Got {TypeName}, caching ({CacheType}).", GetName(baseType, attributeType), added.ToString().ToLowerInvariant()); + _logger.Debug("Got {TypeName}, caching ({CacheType}).", GetName(baseType, attributeType), added.ToString().ToLowerInvariant()); } else { - _logger.Logger.Debug("Got {TypeName}.", GetName(baseType, attributeType)); + _logger.Debug("Got {TypeName}.", GetName(baseType, attributeType)); } return typeList.Types; diff --git a/src/Umbraco.Core/Composing/TypeLoaderExtensions.cs b/src/Umbraco.Core/Composing/TypeLoaderExtensions.cs index 6177151a00..ba57243071 100644 --- a/src/Umbraco.Core/Composing/TypeLoaderExtensions.cs +++ b/src/Umbraco.Core/Composing/TypeLoaderExtensions.cs @@ -42,13 +42,5 @@ namespace Umbraco.Core.Composing { return mgr.GetTypesWithAttribute(); } - - /// - /// Gets all classes implementing ISqlSyntaxProvider and marked with the SqlSyntaxProviderAttribute. - /// - public static IEnumerable GetSqlSyntaxProviders(this TypeLoader mgr) - { - return mgr.GetTypesWithAttribute(); - } } } diff --git a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs index 499984a931..da47c53bf8 100644 --- a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs @@ -14,20 +14,12 @@ namespace Umbraco.Core.Composing where TBuilder : WeightedCollectionBuilderBase where TCollection : IBuilderCollection { - /// - /// Initializes a new instance of the class. - /// - /// - protected WeightedCollectionBuilderBase(IContainer container) - : base(container) - { } - protected abstract TBuilder This { get; } /// /// Clears all types in the collection. /// - /// The buidler. + /// The builder. public TBuilder Clear() { Configure(types => types.Clear()); diff --git a/src/Umbraco.Core/Logging/IProfilingLogger.cs b/src/Umbraco.Core/Logging/IProfilingLogger.cs new file mode 100644 index 0000000000..1d7c231e95 --- /dev/null +++ b/src/Umbraco.Core/Logging/IProfilingLogger.cs @@ -0,0 +1,40 @@ +using System; + +namespace Umbraco.Core.Logging +{ + /// + /// Defines the profiling logging service. + /// + public interface IProfilingLogger : ILogger + { + /// + /// Profiles an action and log as information messages. + /// + DisposableTimer TraceDuration(string startMessage); + + /// + /// Profiles an action and log as information messages. + /// + DisposableTimer TraceDuration(string startMessage, string completeMessage, string failMessage = null); + + /// + /// Profiles an action and log as information messages. + /// + DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null); + + /// + /// Profiles an action and log as debug messages. + /// + DisposableTimer DebugDuration(string startMessage); + + /// + /// Profiles an action and log as debug messages. + /// + DisposableTimer DebugDuration(string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0); + + /// + /// Profiles an action and log as debug messages. + /// + DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0); + } +} diff --git a/src/Umbraco.Core/Logging/ProfilingLogger.cs b/src/Umbraco.Core/Logging/ProfilingLogger.cs index 80560e923a..d642926147 100644 --- a/src/Umbraco.Core/Logging/ProfilingLogger.cs +++ b/src/Umbraco.Core/Logging/ProfilingLogger.cs @@ -3,14 +3,23 @@ namespace Umbraco.Core.Logging { /// - /// Provides debug or trace logging with duration management. + /// Provides logging and profiling services. /// - public sealed class ProfilingLogger + public sealed class ProfilingLogger : IProfilingLogger { + /// + /// Gets the underlying implementation. + /// public ILogger Logger { get; } + /// + /// Gets the underlying implementation. + /// public IProfiler Profiler { get; } + /// + /// Initializes a new instance of the class. + /// public ProfilingLogger(ILogger logger, IProfiler profiler) { Logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -52,5 +61,72 @@ namespace Umbraco.Core.Logging ? new DisposableTimer(Logger, LogLevel.Debug, Profiler, loggerType, startMessage, completeMessage, failMessage, thresholdMilliseconds) : null; } + + #region ILogger + + public bool IsEnabled(Type reporting, LogLevel level) + => Logger.IsEnabled(reporting, level); + + public void Fatal(Type reporting, Exception exception, string message) + => Logger.Fatal(reporting, exception, message); + + public void Fatal(Type reporting, Exception exception) + => Logger.Fatal(reporting, exception); + + public void Fatal(Type reporting, string message) + => Logger.Fatal(reporting, message); + + public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) + => Logger.Fatal(reporting, exception, messageTemplate, propertyValues); + + public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Fatal(reporting, messageTemplate, propertyValues); + + public void Error(Type reporting, Exception exception, string message) + => Logger.Error(reporting, exception, message); + + public void Error(Type reporting, Exception exception) + => Logger.Error(reporting, exception); + + public void Error(Type reporting, string message) + => Logger.Error(reporting, message); + + public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) + => Logger.Error(reporting, exception, messageTemplate, propertyValues); + + public void Error(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Error(reporting, messageTemplate, propertyValues); + + public void Warn(Type reporting, string message) + => Logger.Warn(reporting, message); + + public void Warn(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Warn(reporting, messageTemplate, propertyValues); + + public void Warn(Type reporting, Exception exception, string message) + => Logger.Warn(reporting, exception, message); + + public void Warn(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues) + => Logger.Warn(reporting, exception, messageTemplate, propertyValues); + + public void Info(Type reporting, string message) + => Logger.Info(reporting, message); + + public void Info(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Info(reporting, messageTemplate, propertyValues); + + public void Debug(Type reporting, string message) + => Logger.Debug(reporting, message); + + public void Debug(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Debug(reporting, messageTemplate, propertyValues); + + public void Verbose(Type reporting, string message) + => Logger.Verbose(reporting, message); + + public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues) + => Logger.Verbose(reporting, messageTemplate, propertyValues); + + #endregion } } diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs index 4986eeab02..f5e3892f5d 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseBuilder.cs @@ -369,52 +369,6 @@ namespace Umbraco.Core.Migrations.Install #endregion - #region Utils - - internal static void GiveLegacyAChance(IUmbracoDatabaseFactory factory, ILogger logger) - { - // look for the legacy appSettings key - var legacyConnString = ConfigurationManager.AppSettings[Constants.System.UmbracoConnectionName]; - if (string.IsNullOrWhiteSpace(legacyConnString)) return; - - var test = legacyConnString.ToLowerInvariant(); - if (test.Contains("sqlce4umbraco")) - { - // sql ce - ConfigureEmbeddedDatabaseConnection(factory, logger); - } - else if (test.Contains("tcp:")) - { - // sql azure - SaveConnectionString(legacyConnString, Constants.DbProviderNames.SqlServer, logger); - factory.Configure(legacyConnString, Constants.DbProviderNames.SqlServer); - } - else if (test.Contains("datalayer=mysql")) - { - // mysql - - // strip the datalayer part off - var connectionStringWithoutDatalayer = string.Empty; - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (var variable in legacyConnString.Split(';').Where(x => x.ToLowerInvariant().StartsWith("datalayer") == false)) - connectionStringWithoutDatalayer = $"{connectionStringWithoutDatalayer}{variable};"; - - SaveConnectionString(connectionStringWithoutDatalayer, Constants.DbProviderNames.MySql, logger); - factory.Configure(connectionStringWithoutDatalayer, Constants.DbProviderNames.MySql); - } - else - { - // sql server - SaveConnectionString(legacyConnString, Constants.DbProviderNames.SqlServer, logger); - factory.Configure(legacyConnString, Constants.DbProviderNames.SqlServer); - } - - // remove the legacy connection string, so we don't end up in a loop if something goes wrong - GlobalSettings.RemoveSetting(Constants.System.UmbracoConnectionName); - } - - #endregion - #region Database Schema internal DatabaseSchemaResult ValidateDatabaseSchema() diff --git a/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs b/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs index ba3eb96ce9..b23d4f1c9c 100644 --- a/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs +++ b/src/Umbraco.Core/Migrations/PostMigrationCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.Migrations { public class PostMigrationCollectionBuilder : LazyCollectionBuilderBase { - public PostMigrationCollectionBuilder(IContainer container) - : base(container) - { } - protected override PostMigrationCollectionBuilder This => this; protected override Lifetime CollectionLifetime => Lifetime.Transient; diff --git a/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs b/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs index 65bfbcdbaf..28e19088bf 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MapperCollectionBuilder.cs @@ -4,15 +4,11 @@ namespace Umbraco.Core.Persistence.Mappers { public class MapperCollectionBuilder : LazyCollectionBuilderBase { - public MapperCollectionBuilder(IContainer container) - : base(container) - { } - protected override MapperCollectionBuilder This => this; - protected override void Initialize() + public override void Initialize(IContainer container) { - base.Initialize(); + base.Initialize(container); // default initializer registers // - service MapperCollectionBuilder, returns MapperCollectionBuilder @@ -23,7 +19,7 @@ namespace Umbraco.Core.Persistence.Mappers Container.Register(factory => factory.GetInstance()); } - public MapperCollectionBuilder AddCore() + public MapperCollectionBuilder AddCoreMappers() { Add(); Add(); diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs index d69786fbfc..5cf9fa3af8 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs @@ -11,7 +11,6 @@ namespace Umbraco.Core.Persistence.SqlSyntax /// /// Represents an SqlSyntaxProvider for MySql /// - [SqlSyntaxProvider(Constants.DbProviderNames.MySql)] public class MySqlSyntaxProvider : SqlSyntaxProviderBase { private readonly ILogger _logger; @@ -334,7 +333,7 @@ ORDER BY TABLE_NAME, INDEX_NAME", switch (systemMethod) { case SystemMethods.NewGuid: - return null; // NOT SUPPORTED! + return null; // NOT SUPPORTED! case SystemMethods.CurrentDateTime: return "CURRENT_TIMESTAMP"; } diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs index 75fc9c0b69..8f39e36fb9 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs @@ -4,14 +4,12 @@ using System.Linq; using NPoco; using Umbraco.Core.Persistence.DatabaseAnnotations; using Umbraco.Core.Persistence.DatabaseModelDefinitions; -using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Persistence.SqlSyntax { /// /// Represents an SqlSyntaxProvider for Sql Ce /// - [SqlSyntaxProvider(Constants.DbProviderNames.SqlCe)] public class SqlCeSyntaxProvider : MicrosoftSqlSyntaxProviderBase { public override Sql SelectTop(Sql sql, int top) diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs index 90a2215e3d..d9bfe85098 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs @@ -11,29 +11,9 @@ namespace Umbraco.Core.Persistence.SqlSyntax /// /// Represents an SqlSyntaxProvider for Sql Server. /// - [SqlSyntaxProvider(Constants.DbProviderNames.SqlServer)] public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase { - // IUmbracoDatabaseFactory to be lazily injected - public SqlServerSyntaxProvider(Lazy lazyScopeProvider) - { - _serverVersion = new Lazy(() => - { - var scopeProvider = lazyScopeProvider.Value; - if (scopeProvider == null) - throw new InvalidOperationException("Failed to determine Sql Server version (no scope provider)."); - using (var scope = scopeProvider.CreateScope()) - { - var version = DetermineVersion(scope.Database); - scope.Complete(); - return version; - } - }); - } - - private readonly Lazy _serverVersion; - - internal ServerVersionInfo ServerVersion => _serverVersion.Value; + internal ServerVersionInfo ServerVersion { get; private set; } internal enum VersionName { @@ -62,19 +42,31 @@ namespace Umbraco.Core.Persistence.SqlSyntax internal class ServerVersionInfo { - public string Edition { get; set; } - public string InstanceName { get; set; } - public string ProductVersion { get; set; } - public VersionName ProductVersionName { get; private set; } - public EngineEdition EngineEdition { get; set; } - public bool IsAzure => EngineEdition == EngineEdition.Azure; - public string MachineName { get; set; } - public string ProductLevel { get; set; } - - public void Initialize() + public ServerVersionInfo() { - ProductVersionName = MapProductVersion(ProductVersion); + ProductVersionName = VersionName.Unknown; + EngineEdition = EngineEdition.Unknown; } + + public ServerVersionInfo(string edition, string instanceName, string productVersion, EngineEdition engineEdition, string machineName, string productLevel) + { + Edition = edition; + InstanceName = instanceName; + ProductVersion = productVersion; + ProductVersionName = MapProductVersion(ProductVersion); + EngineEdition = engineEdition; + MachineName = machineName; + ProductLevel = productLevel; + } + + public string Edition { get; } + public string InstanceName { get; } + public string ProductVersion { get; } + public VersionName ProductVersionName { get; } + public EngineEdition EngineEdition { get; } + public bool IsAzure => EngineEdition == EngineEdition.Azure; + public string MachineName { get; } + public string ProductLevel { get; } } private static VersionName MapProductVersion(string productVersion) @@ -105,8 +97,14 @@ namespace Umbraco.Core.Persistence.SqlSyntax } } - private static ServerVersionInfo DetermineVersion(IUmbracoDatabase database) + internal ServerVersionInfo GetSetVersion(string connectionString, string providerName) { + var factory = DbProviderFactories.GetFactory(providerName); + var connection = factory.CreateConnection(); + + if (connection == null) + throw new InvalidOperationException($"Could not create a connection for provider \"{providerName}\"."); + // Edition: "Express Edition", "Windows Azure SQL Database..." // EngineEdition: 1/Desktop 2/Standard 3/Enterprise 4/Express 5/Azure // ProductLevel: RTM, SPx, CTP... @@ -123,44 +121,28 @@ namespace Umbraco.Core.Persistence.SqlSyntax SERVERPROPERTY('ResourceLastUpdateDateTime') ResourceLastUpdateDateTime, SERVERPROPERTY('ProductLevel') ProductLevel;"; - try - { - var version = database.Fetch(sql).First(); - version.Initialize(); - return version; - } - catch (Exception e) - { - // can't ignore, really - throw new Exception("Failed to determine Sql Server version (see inner exception).", e); - } - } - - internal static VersionName GetVersionName(string connectionString, string providerName) - { - var factory = DbProviderFactories.GetFactory(providerName); - var connection = factory.CreateConnection(); - - if (connection == null) - throw new InvalidOperationException($"Could not create a connection for provider \"{providerName}\"."); - connection.ConnectionString = connectionString; + ServerVersionInfo version; using (connection) { try { connection.Open(); var command = connection.CreateCommand(); - command.CommandText = "SELECT SERVERPROPERTY('ProductVersion');"; - var productVersion = command.ExecuteScalar().ToString(); + command.CommandText = sql; + using (var reader = command.ExecuteReader()) + { + version = new ServerVersionInfo(reader.GetString(0), reader.GetString(2), reader.GetString(3), (EngineEdition) reader.GetInt32(5), reader.GetString(7), reader.GetString(9)); + } connection.Close(); - return MapProductVersion(productVersion); } catch { - return VersionName.Unknown; + version = new ServerVersionInfo(); // all unknown } } + + return ServerVersion = version; } /// diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderAttribute.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderAttribute.cs deleted file mode 100644 index 191ee86bac..0000000000 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderAttribute.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace Umbraco.Core.Persistence.SqlSyntax -{ - /// - /// Attribute for implementations of an ISqlSyntaxProvider - /// - [AttributeUsage(AttributeTargets.Class)] - public class SqlSyntaxProviderAttribute : Attribute - { - public SqlSyntaxProviderAttribute(string providerName) - { - ProviderName = providerName; - } - - /// - /// Gets or sets the ProviderName that corresponds to the sql syntax in a provider. - /// - public string ProviderName { get; set; } - } -} diff --git a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs index ea597007b7..e55f462a7b 100644 --- a/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Core/Persistence/UmbracoDatabaseFactory.cs @@ -1,14 +1,11 @@ using System; -using System.Collections.Generic; using System.Configuration; using System.Data.Common; -using System.Linq; using System.Threading; using NPoco; using NPoco.FluentMappings; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; -using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence.FaultHandling; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; @@ -27,12 +24,11 @@ namespace Umbraco.Core.Persistence /// internal class UmbracoDatabaseFactory : DisposableObject, IUmbracoDatabaseFactory { - private readonly ISqlSyntaxProvider[] _sqlSyntaxProviders; - private readonly IMapperCollection _mappers; + private readonly Lazy _mappers; private readonly ILogger _logger; - private readonly SqlContext _sqlContext = new SqlContext(); private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); + private SqlContext _sqlContext; private DatabaseFactory _npocoDatabaseFactory; private IPocoDataFactory _pocoDataFactory; private string _connectionString; @@ -51,24 +47,20 @@ namespace Umbraco.Core.Persistence /// /// Initializes a new instance of the . /// - /// Used by injection. - public UmbracoDatabaseFactory(IEnumerable sqlSyntaxProviders, ILogger logger, IMapperCollection mappers) - : this(Constants.System.UmbracoConnectionName, sqlSyntaxProviders, logger, mappers) - { - if (Configured == false) - DatabaseBuilder.GiveLegacyAChance(this, logger); - } + /// Used by core runtime. + public UmbracoDatabaseFactory(ILogger logger, Lazy mappers) + : this(Constants.System.UmbracoConnectionName, logger, mappers) + { } /// /// Initializes a new instance of the . /// /// Used by the other ctor and in tests. - public UmbracoDatabaseFactory(string connectionStringName, IEnumerable sqlSyntaxProviders, ILogger logger, IMapperCollection mappers) + public UmbracoDatabaseFactory(string connectionStringName, ILogger logger, Lazy mappers) { if (string.IsNullOrWhiteSpace(connectionStringName)) throw new ArgumentNullOrEmptyException(nameof(connectionStringName)); _mappers = mappers ?? throw new ArgumentNullException(nameof(mappers)); - _sqlSyntaxProviders = sqlSyntaxProviders?.ToArray() ?? throw new ArgumentNullException(nameof(sqlSyntaxProviders)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); var settings = ConfigurationManager.ConnectionStrings[connectionStringName]; @@ -92,10 +84,9 @@ namespace Umbraco.Core.Persistence /// Initializes a new instance of the . /// /// Used in tests. - public UmbracoDatabaseFactory(string connectionString, string providerName, IEnumerable sqlSyntaxProviders, ILogger logger, IMapperCollection mappers) + public UmbracoDatabaseFactory(string connectionString, string providerName, ILogger logger, Lazy mappers) { _mappers = mappers ?? throw new ArgumentNullException(nameof(mappers)); - _sqlSyntaxProviders = sqlSyntaxProviders?.ToArray() ?? throw new ArgumentNullException(nameof(sqlSyntaxProviders)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); if (string.IsNullOrWhiteSpace(connectionString) || string.IsNullOrWhiteSpace(providerName)) @@ -139,7 +130,7 @@ namespace Umbraco.Core.Persistence if (setting.IsNullOrWhiteSpace() || !setting.StartsWith("SqlServer.") || !Enum.TryParse(setting.Substring("SqlServer.".Length), out var versionName, true)) { - versionName = SqlServerSyntaxProvider.GetVersionName(_connectionString, _providerName); + versionName = ((SqlServerSyntaxProvider) _sqlSyntax).GetSetVersion(_connectionString, _providerName).ProductVersionName; } else { @@ -165,7 +156,7 @@ namespace Umbraco.Core.Persistence } /// - public ISqlContext SqlContext => _sqlContext; + public ISqlContext SqlContext => _sqlContext ?? (_sqlContext = new SqlContext(_sqlSyntax, _databaseType, _pocoDataFactory, _mappers.Value)); /// public void ConfigureForUpgrade() @@ -218,10 +209,6 @@ namespace Umbraco.Core.Persistence if (_npocoDatabaseFactory == null) throw new NullReferenceException("The call to UmbracoDatabaseFactory.Config yielded a null UmbracoDatabaseFactory instance."); - // can initialize now because it is the UmbracoDatabaseFactory that determines - // the sql syntax, poco data factory, and database type - _sqlContext.Initialize(_sqlSyntax, _databaseType, _pocoDataFactory, _mappers); - _logger.Debug("Configured."); Configured = true; } @@ -245,17 +232,17 @@ namespace Umbraco.Core.Persistence // gets the sql syntax provider that corresponds, from attribute private ISqlSyntaxProvider GetSqlSyntaxProvider(string providerName) { - var name = providerName.ToLowerInvariant(); - var provider = _sqlSyntaxProviders.FirstOrDefault(x => - x.GetType() - .FirstAttribute() - .ProviderName.ToLowerInvariant() - .Equals(name)); - if (provider != null) return provider; - throw new InvalidOperationException($"Unknown provider name \"{providerName}\""); - - // previously we'd try to return SqlServerSyntaxProvider by default but this is bad - //provider = _syntaxProviders.FirstOrDefault(x => x.GetType() == typeof(SqlServerSyntaxProvider)); + switch (providerName) + { + case Constants.DbProviderNames.MySql: + return new MySqlSyntaxProvider(_logger); + case Constants.DbProviderNames.SqlCe: + return new SqlCeSyntaxProvider(); + case Constants.DbProviderNames.SqlServer: + return new SqlServerSyntaxProvider(); + default: + throw new InvalidOperationException($"Unknown provider name \"{providerName}\""); + } } // ensures that the database is configured, else throws @@ -277,7 +264,7 @@ namespace Umbraco.Core.Persistence // method used by NPoco's UmbracoDatabaseFactory to actually create the database instance private UmbracoDatabase CreateDatabaseInstance() { - return new UmbracoDatabase(_connectionString, _sqlContext, _dbProviderFactory, _logger, _connectionRetryPolicy, _commandRetryPolicy); + return new UmbracoDatabase(_connectionString, SqlContext, _dbProviderFactory, _logger, _connectionRetryPolicy, _commandRetryPolicy); } protected override void DisposeResources() diff --git a/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs index c23972c684..c0c0a3651e 100644 --- a/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.PropertyEditors { public class DataEditorCollectionBuilder : LazyCollectionBuilderBase { - public DataEditorCollectionBuilder(IContainer container) - : base(container) - { } - protected override DataEditorCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs index 3ba6f4e402..8f7c68c813 100644 --- a/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/ManifestValueValidatorCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.PropertyEditors { internal class ManifestValueValidatorCollectionBuilder : LazyCollectionBuilderBase { - public ManifestValueValidatorCollectionBuilder(IContainer container) - : base(container) - { } - protected override ManifestValueValidatorCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs index e95159ed0b..a64fe8c43a 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.PropertyEditors { public class PropertyValueConverterCollectionBuilder : OrderedCollectionBuilderBase { - public PropertyValueConverterCollectionBuilder(IContainer container) - : base(container) - { } - protected override PropertyValueConverterCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 3004c7566a..2ae7c66136 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -15,9 +15,9 @@ using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; using Umbraco.Core.Services.Implement; +using Umbraco.Core.Sync; namespace Umbraco.Core.Runtime { @@ -28,39 +28,71 @@ namespace Umbraco.Core.Runtime /// should be possible to use this runtime in console apps. public class CoreRuntime : IRuntime { - private BootLoader _bootLoader; + private Components.Components _components; private RuntimeState _state; + /// + /// Gets the logger. + /// + protected ILogger Logger { get; private set; } + + /// + /// Gets the profiling logger. + /// + protected IProfilingLogger ProfilingLogger { get; private set; } + /// public virtual void Boot(IContainer container) { // assign current container Current.Container = container; - // register the essential stuff, - // ie the global application logger - // (profiler etc depend on boot manager) + // create and register the essential services + // ie the bare minimum required to boot + + var composition = new Composition(container, RuntimeLevel.Boot); + + // loggers var logger = GetLogger(); container.RegisterInstance(logger); - // now it is ok to use Current.Logger + Logger = logger; + var profiler = GetProfiler(); + container.RegisterInstance(profiler); + var profilingLogger = new ProfilingLogger(logger, profiler); + container.RegisterInstance(profilingLogger); + ProfilingLogger = profilingLogger; - ConfigureUnhandledException(logger); - ConfigureAssemblyResolve(logger); + // application environment + ConfigureUnhandledException(); + ConfigureAssemblyResolve(); + ConfigureApplicationRootPath(); - Compose(container); + // application caches + var appCaches = GetAppCaches(); + container.RegisterInstance(appCaches); + var runtimeCache = appCaches.RuntimeCache; + container.RegisterInstance(runtimeCache); - // prepare essential stuff + // database factory + var databaseFactory = new UmbracoDatabaseFactory(logger, new Lazy(container.GetInstance)); + container.RegisterSingleton(factory => factory.GetInstance().SqlContext); - var path = GetApplicationRootPath(); - if (string.IsNullOrWhiteSpace(path) == false) - IOHelper.SetRootDirectory(path); + // type loader + var globalSettings = UmbracoConfig.For.GlobalSettings(); + var typeLoader = new TypeLoader(runtimeCache, globalSettings, profilingLogger); + container.RegisterInstance(typeLoader); - _state = (RuntimeState) container.GetInstance(); - _state.Level = RuntimeLevel.Boot; + // runtime state + _state = new RuntimeState(logger, + UmbracoConfig.For.UmbracoSettings(), UmbracoConfig.For.GlobalSettings(), + new Lazy(container.GetInstance), + new Lazy(container.GetInstance)) + { + Level = RuntimeLevel.Boot + }; + container.RegisterInstance(_state); - Logger = container.GetInstance(); - Profiler = container.GetInstance(); - ProfilingLogger = container.GetInstance(); + Compose(composition); // the boot loader boots using a container scope, so anything that is PerScope will // be disposed after the boot loader has booted, and anything else will remain. @@ -76,18 +108,33 @@ namespace Umbraco.Core.Runtime "Booted.", "Boot failed.")) { - // throws if not full-trust - new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted).Demand(); - try { - Logger.Debug("Runtime: {Runtime}", GetType().FullName); + // throws if not full-trust + new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted).Demand(); - AquireMainDom(container); - DetermineRuntimeLevel(container); - var componentTypes = ResolveComponentTypes(); - _bootLoader = new BootLoader(container); - _bootLoader.Boot(componentTypes, _state.Level); + logger.Debug("Runtime: {Runtime}", GetType().FullName); + + var mainDom = AquireMainDom(); + container.RegisterInstance(mainDom); + + DetermineRuntimeLevel(databaseFactory); + + var componentTypes = ResolveComponentTypes(typeLoader); + _components = new Components.Components(composition, componentTypes, profilingLogger); + + _components.Compose(); + + // no Current.Container only Current.Factory? + //factory = register.Compile(); + + // fixme at that point we can start actually getting things from the container + // but, ideally, not before = need to detect everything we use!! + + // at that point, getting things from the container is ok + // fixme split IRegistry vs IFactory + + _components.Initialize(); } catch (Exception e) { @@ -105,15 +152,7 @@ namespace Umbraco.Core.Runtime } } - /// - /// Gets a logger. - /// - protected virtual ILogger GetLogger() - { - return SerilogLogger.CreateWithDefaultConfiguration(); - } - - protected virtual void ConfigureUnhandledException(ILogger logger) + protected virtual void ConfigureUnhandledException() { //take care of unhandled exceptions - there is nothing we can do to // prevent the launch process to go down but at least we can try @@ -126,33 +165,40 @@ namespace Umbraco.Core.Runtime var msg = "Unhandled exception in AppDomain"; if (isTerminating) msg += " (terminating)"; msg += "."; - logger.Error(exception, msg); + Logger.Error(exception, msg); }; } - protected virtual void ConfigureAssemblyResolve(ILogger logger) + protected virtual void ConfigureAssemblyResolve() { // When an assembly can't be resolved. In here we can do magic with the assembly name and try loading another. // This is used for loading a signed assembly of AutoMapper (v. 3.1+) without having to recompile old code. AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { // ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again - // do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow + // do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stack overflow if (args.Name.StartsWith("AutoMapper") && args.Name.EndsWith("PublicKeyToken=null")) return Assembly.Load(args.Name.Replace(", PublicKeyToken=null", ", PublicKeyToken=be96cd2c38ef1005")); return null; }; } - - private void AquireMainDom(IContainer container) + protected virtual void ConfigureApplicationRootPath() { - using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Aquired.")) + var path = GetApplicationRootPath(); + if (string.IsNullOrWhiteSpace(path) == false) + IOHelper.SetRootDirectory(path); + } + + private MainDom AquireMainDom() + { + using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Acquired.")) { try { - var mainDom = container.GetInstance(); + var mainDom = new MainDom(Logger); mainDom.Acquire(); + return mainDom; } catch { @@ -163,38 +209,38 @@ namespace Umbraco.Core.Runtime } // internal for tests - internal void DetermineRuntimeLevel(IContainer container) + internal void DetermineRuntimeLevel(IUmbracoDatabaseFactory databaseFactory) { using (var timer = ProfilingLogger.DebugDuration("Determining runtime level.", "Determined.")) { try { - var dbfactory = container.GetInstance(); - SetRuntimeStateLevel(dbfactory, Logger); + _state.Level = DetermineRuntimeLevel2(databaseFactory); - Logger.Debug("Runtime level: {RuntimeLevel}", _state.Level); + ProfilingLogger.Debug("Runtime level: {RuntimeLevel}", _state.Level); if (_state.Level == RuntimeLevel.Upgrade) { - Logger.Debug("Configure database factory for upgrades."); - dbfactory.ConfigureForUpgrade(); + ProfilingLogger.Debug("Configure database factory for upgrades."); + databaseFactory.ConfigureForUpgrade(); } } catch { + _state.Level = RuntimeLevel.BootFailed; timer.Fail(); throw; } } } - private IEnumerable ResolveComponentTypes() + private IEnumerable ResolveComponentTypes(TypeLoader typeLoader) { using (var timer = ProfilingLogger.TraceDuration("Resolving component types.", "Resolved.")) { try { - return GetComponentTypes(); + return GetComponentTypes(typeLoader); } catch { @@ -209,97 +255,56 @@ namespace Umbraco.Core.Runtime { using (ProfilingLogger.DebugDuration("Terminating Umbraco.", "Terminated.")) { - _bootLoader?.Terminate(); + _components?.Terminate(); } } /// /// Composes the runtime. /// - public virtual void Compose(IContainer container) + public virtual void Compose(Composition composition) { + var container = composition.Container; + // compose the very essential things that are needed to bootstrap, before anything else, // and only these things - the rest should be composed in runtime components - - // register basic things - container.RegisterSingleton(); - container.RegisterSingleton(); - container.RegisterSingleton(); + // FIXME should be essentially empty! move all to component! container.ComposeConfiguration(); - // register caches - // need the deep clone runtime cache profiver to ensure entities are cached properly, ie - // are cloned in and cloned out - no request-based cache here since no web-based context, - // will be overriden later or - container.RegisterSingleton(_ => new CacheHelper( - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), - new StaticCacheProvider(), - NullCacheProvider.Instance, - new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); - container.RegisterSingleton(f => f.GetInstance().RuntimeCache); - - // register the plugin manager - container.RegisterSingleton(f => new TypeLoader(f.GetInstance(), f.GetInstance(), f.GetInstance())); - - // register syntax providers - required by database factory - GetAllInstances or an IEnumerable can get them - container.Register(); - container.Register(); - container.Register(); - // register persistence mappers - required by database factory so needs to be done here // means the only place the collection can be modified is in a runtime - afterwards it // has been frozen and it is too late - var mapperCollectionBuilder = container.RegisterCollectionBuilder(); - ComposeMapperCollection(mapperCollectionBuilder); - - // register database factory - required to check for migrations - // will be initialized with syntax providers and a logger, and will try to configure - // from the default connection string name, if possible, else will remain non-configured - // until properly configured (eg when installing) - container.RegisterSingleton(); - container.RegisterSingleton(f => f.GetInstance().SqlContext); + composition.GetCollectionBuilder().AddCoreMappers(); // register the scope provider container.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor container.RegisterSingleton(f => f.GetInstance()); container.RegisterSingleton(f => f.GetInstance()); - - // register MainDom - container.RegisterSingleton(); } - protected virtual void ComposeMapperCollection(MapperCollectionBuilder builder) - { - builder.AddCore(); - } - - private void SetRuntimeStateLevel(IUmbracoDatabaseFactory databaseFactory, ILogger logger) + private RuntimeLevel DetermineRuntimeLevel2(IUmbracoDatabaseFactory databaseFactory) { var localVersion = UmbracoVersion.LocalVersion; // the local, files, version var codeVersion = _state.SemanticVersion; // the executing code version var connect = false; - // we don't know yet - _state.Level = RuntimeLevel.Unknown; - if (localVersion == null) { // there is no local version, we are not installed - logger.Debug("No local version, need to install Umbraco."); - _state.Level = RuntimeLevel.Install; + Logger.Debug("No local version, need to install Umbraco."); + return RuntimeLevel.Install; } - else if (localVersion < codeVersion) + + if (localVersion < codeVersion) { // there *is* a local version, but it does not match the code version // need to upgrade - logger.Debug("Local version '{LocalVersion}' < code version '{CodeVersion}', need to upgrade Umbraco.", localVersion, codeVersion); - _state.Level = RuntimeLevel.Upgrade; + Logger.Debug("Local version '{LocalVersion}' < code version '{CodeVersion}', need to upgrade Umbraco.", localVersion, codeVersion); } else if (localVersion > codeVersion) { - logger.Warn("Local version '{LocalVersion}' > code version '{CodeVersion}', downgrading is not supported.", localVersion, codeVersion); - _state.Level = RuntimeLevel.BootFailed; + Logger.Warn("Local version '{LocalVersion}' > code version '{CodeVersion}', downgrading is not supported.", localVersion, codeVersion); // in fact, this is bad enough that we want to throw throw new BootFailedException($"Local version \"{localVersion}\" > code version \"{codeVersion}\", downgrading is not supported."); @@ -308,14 +313,10 @@ namespace Umbraco.Core.Runtime { // local version *does* match code version, but the database is not configured // install (again? this is a weird situation...) - logger.Debug("Database is not configured, need to install Umbraco."); - _state.Level = RuntimeLevel.Install; + Logger.Debug("Database is not configured, need to install Umbraco."); + return RuntimeLevel.Install; } - // install? not going to test anything else - if (_state.Level == RuntimeLevel.Install) - return; - // else, keep going, // anything other than install wants a database - see if we can connect // (since this is an already existing database, assume localdb is ready) @@ -323,15 +324,14 @@ namespace Umbraco.Core.Runtime { connect = databaseFactory.CanConnect; if (connect) break; - logger.Debug("Could not immediately connect to database, trying again."); + Logger.Debug("Could not immediately connect to database, trying again."); Thread.Sleep(1000); } if (connect == false) { // cannot connect to configured database, this is bad, fail - logger.Debug("Could not connect to database."); - _state.Level = RuntimeLevel.BootFailed; + Logger.Debug("Could not connect to database."); // in fact, this is bad enough that we want to throw throw new BootFailedException("A connection string is configured but Umbraco could not connect to the database."); @@ -347,20 +347,19 @@ namespace Umbraco.Core.Runtime bool noUpgrade; try { - noUpgrade = EnsureUmbracoUpgradeState(databaseFactory, logger); + noUpgrade = EnsureUmbracoUpgradeState(databaseFactory); } catch (Exception e) { // can connect to the database but cannot check the upgrade state... oops - logger.Warn(e, "Could not check the upgrade state."); + Logger.Warn(e, "Could not check the upgrade state."); throw new BootFailedException("Could not check the upgrade state.", e); } if (noUpgrade) { // the database version matches the code & files version, all clear, can run - _state.Level = RuntimeLevel.Run; - return; + return RuntimeLevel.Run; } // the db version does not match... but we do have a migration table @@ -368,11 +367,11 @@ namespace Umbraco.Core.Runtime // although the files version matches the code version, the database version does not // which means the local files have been upgraded but not the database - need to upgrade - logger.Debug("Has not reached the final upgrade step, need to upgrade Umbraco."); - _state.Level = RuntimeLevel.Upgrade; + Logger.Debug("Has not reached the final upgrade step, need to upgrade Umbraco."); + return RuntimeLevel.Upgrade; } - protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) + protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory) { var umbracoPlan = new UmbracoPlan(); var stateValueKey = Upgrader.GetStateValueKey(umbracoPlan); @@ -384,31 +383,53 @@ namespace Umbraco.Core.Runtime _state.FinalMigrationState = umbracoPlan.FinalState; } - logger.Debug("Final upgrade state is {FinalMigrationState}, database contains {DatabaseState}", _state.FinalMigrationState, _state.CurrentMigrationState ?? ""); + Logger.Debug("Final upgrade state is {FinalMigrationState}, database contains {DatabaseState}", _state.FinalMigrationState, _state.CurrentMigrationState ?? ""); return _state.CurrentMigrationState == _state.FinalMigrationState; } - #region Locals - - protected ILogger Logger { get; private set; } - - protected IProfiler Profiler { get; private set; } - - protected ProfilingLogger ProfilingLogger { get; private set; } - - #endregion - #region Getters // getters can be implemented by runtimes inheriting from CoreRuntime - // fixme - inject! no Current! - protected virtual IEnumerable GetComponentTypes() => Current.TypeLoader.GetTypes(); + /// + /// Gets all component types. + /// + protected virtual IEnumerable GetComponentTypes(TypeLoader typeLoader) + => typeLoader.GetTypes(); + + /// + /// Gets a logger. + /// + protected virtual ILogger GetLogger() + => SerilogLogger.CreateWithDefaultConfiguration(); + + /// + /// Gets a profiler. + /// + protected virtual IProfiler GetProfiler() + => new LogProfiler(ProfilingLogger); + + /// + /// Gets the application caches. + /// + protected virtual CacheHelper GetAppCaches() + { + // need the deep clone runtime cache provider to ensure entities are cached properly, ie + // are cloned in and cloned out - no request-based cache here since no web-based context, + // is overriden by the web runtime + + return new CacheHelper( + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()), + new StaticCacheProvider(), + NullCacheProvider.Instance, + new IsolatedRuntimeCache(type => new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + } // by default, returns null, meaning that Umbraco should auto-detect the application root path. // override and return the absolute path to the Umbraco site/solution, if needed - protected virtual string GetApplicationRootPath() => null; + protected virtual string GetApplicationRootPath() + => null; #endregion } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 34fd04d181..058c2ed593 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -47,7 +47,7 @@ namespace Umbraco.Core.Runtime composition.Container.RegisterSingleton(); // register our predefined validators - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() .Add() .Add() @@ -56,7 +56,7 @@ namespace Umbraco.Core.Runtime .Add(); // properties and parameters derive from data editors - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(factory => factory.GetInstance().GetDataEditors()); composition.Container.RegisterSingleton(); composition.Container.RegisterSingleton(); @@ -83,13 +83,13 @@ namespace Umbraco.Core.Runtime factory.GetInstance(), true, new DatabaseServerMessengerOptions())); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(factory => factory.GetInstance().GetCacheRefreshers()); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(f => f.GetInstance().GetPackageActions()); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append(factory => factory.GetInstance().GetTypes()); composition.Container.RegisterSingleton(); @@ -97,10 +97,10 @@ namespace Umbraco.Core.Runtime composition.Container.RegisterSingleton(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append(); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(factory => factory.GetInstance().GetTypes()); composition.Container.RegisterSingleton(factory => new MigrationBuilder(composition.Container)); diff --git a/src/Umbraco.Core/RuntimeState.cs b/src/Umbraco.Core/RuntimeState.cs index 4f6f56531b..4ba75ed89f 100644 --- a/src/Umbraco.Core/RuntimeState.cs +++ b/src/Umbraco.Core/RuntimeState.cs @@ -17,76 +17,67 @@ namespace Umbraco.Core internal class RuntimeState : IRuntimeState { private readonly ILogger _logger; - private readonly Lazy _serverRegistrar; - private readonly Lazy _mainDom; private readonly IUmbracoSettingsSection _settings; private readonly IGlobalSettings _globalSettings; private readonly HashSet _applicationUrls = new HashSet(); private RuntimeLevel _level; + private Lazy _mainDom; + private Lazy _serverRegistrar; /// /// Initializes a new instance of the class. /// /// A logger. - /// A (lazy) server registrar. - /// A (lazy) MainDom. - public RuntimeState(ILogger logger, Lazy serverRegistrar, Lazy mainDom, IUmbracoSettingsSection settings, IGlobalSettings globalSettings) + /// Umbraco settings. + /// Global settings. + public RuntimeState(ILogger logger, IUmbracoSettingsSection settings, IGlobalSettings globalSettings, + Lazy mainDom, Lazy serverRegistrar) { _logger = logger; - _serverRegistrar = serverRegistrar; - _mainDom = mainDom; _settings = settings; _globalSettings = globalSettings; + _mainDom = mainDom; + _serverRegistrar = serverRegistrar; } + /// + /// Gets the server registrar. + /// + /// + /// This is NOT exposed in the interface. + /// private IServerRegistrar ServerRegistrar => _serverRegistrar.Value; /// /// Gets the application MainDom. /// - /// This is NOT exposed in the interface as MainDom is internal. + /// + /// This is NOT exposed in the interface as MainDom is internal. + /// public MainDom MainDom => _mainDom.Value; - /// - /// Gets the version of the executing code. - /// + /// public Version Version => UmbracoVersion.Current; - /// - /// Gets the version comment of the executing code. - /// + /// public string VersionComment => UmbracoVersion.Comment; - /// - /// Gets the semantic version of the executing code. - /// + /// public SemVersion SemanticVersion => UmbracoVersion.SemanticVersion; - /// - /// Gets a value indicating whether the application is running in debug mode. - /// + /// public bool Debug { get; } = GlobalSettings.DebugMode; - /// - /// Gets a value indicating whether the runtime is the current main domain. - /// + /// public bool IsMainDom => MainDom.IsMainDom; - /// - /// Get the server's current role. - /// + /// public ServerRole ServerRole => ServerRegistrar.GetCurrentServerRole(); - /// - /// Gets the Umbraco application url. - /// - /// This is eg "http://www.example.com". + /// public Uri ApplicationUrl { get; private set; } - /// - /// Gets the Umbraco application virtual path. - /// - /// This is either "/" or eg "/virtual". + /// public string ApplicationVirtualPath { get; } = HttpRuntime.AppDomainAppVirtualPath; /// @@ -95,9 +86,7 @@ namespace Umbraco.Core /// public string FinalMigrationState { get; internal set; } - /// - /// Gets the runtime level of execution. - /// + /// public RuntimeLevel Level { get => _level; @@ -137,9 +126,7 @@ namespace Umbraco.Core return _runLevel.WaitHandle.WaitOne(timeout); } - /// - /// Gets the exception that caused the boot to fail. - /// + /// public BootFailedException BootFailedException { get; internal set; } } } diff --git a/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs b/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs index 7c45bf0884..5183c28e15 100644 --- a/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs +++ b/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core.Strings { public class UrlSegmentProviderCollectionBuilder : OrderedCollectionBuilderBase { - public UrlSegmentProviderCollectionBuilder(IContainer container) - : base(container) - { } - protected override UrlSegmentProviderCollectionBuilder This => this; } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 1b517ae1f9..57f7208d03 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -155,7 +155,7 @@ - + @@ -335,6 +335,7 @@ + @@ -1222,7 +1223,6 @@ - diff --git a/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs b/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs index a92d340b48..2f73a2b489 100644 --- a/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs +++ b/src/Umbraco.Core/_Legacy/PackageActions/PackageActionCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Core._Legacy.PackageActions { internal class PackageActionCollectionBuilder : LazyCollectionBuilderBase { - public PackageActionCollectionBuilder(IContainer container) - : base(container) - { } - protected override PackageActionCollectionBuilder This => this; } } diff --git a/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs index 0505974304..ee2e75cfad 100644 --- a/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs +++ b/src/Umbraco.Tests.Benchmarks/BulkInsertBenchmarks.cs @@ -4,18 +4,12 @@ using System.Data.SqlServerCe; using System.IO; using System.Linq; using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Diagnosers; -using BenchmarkDotNet.Horology; -using BenchmarkDotNet.Jobs; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; using Umbraco.Tests.Benchmarks.Config; using Umbraco.Tests.TestHelpers; @@ -34,13 +28,11 @@ namespace Umbraco.Tests.Benchmarks { IScopeProvider f = null; var l = new Lazy(() => f); - var p = new SqlServerSyntaxProvider(l); var factory = new UmbracoDatabaseFactory( "server=.\\SQLExpress;database=YOURDB;user id=YOURUSER;password=YOURPASS", Constants.DatabaseProviders.SqlServer, - new [] { p }, logger, - new MapperCollection(Enumerable.Empty())); + new Lazy(() => new MapperCollection(Enumerable.Empty()))); return factory.CreateDatabase(); } @@ -49,9 +41,8 @@ namespace Umbraco.Tests.Benchmarks var f = new UmbracoDatabaseFactory( cstr, Constants.DatabaseProviders.SqlCe, - new[] { new SqlCeSyntaxProvider() }, logger, - new MapperCollection(Enumerable.Empty())); + new Lazy(() => new MapperCollection(Enumerable.Empty()))); return f.CreateDatabase(); } diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index 554194fd91..d3b0b6cda8 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -4,6 +4,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Sync; @@ -21,11 +22,12 @@ namespace Umbraco.Tests.Cache.DistributedCache public void Setup() { var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); container.Register(_ => new TestServerRegistrar()); container.RegisterSingleton(_ => new TestServerMessenger()); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(); _distributedCache = new Umbraco.Web.Cache.DistributedCache(); diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index e4a15a2ac2..a0ab75f0f9 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Cache.PublishedCache { base.Compose(); - Container.GetInstance() + Composition.GetCollectionBuilder() .Clear() .Append(); } diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index a537aac4ae..111a1370ee 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -27,10 +27,8 @@ namespace Umbraco.Tests.Components var mock = new Mock(); - var testObjects = new TestObjects(null); var logger = Mock.Of(); - var s = testObjects.GetDefaultSqlSyntaxProviders(logger); - var f = new UmbracoDatabaseFactory(s, logger, new MapperCollection(Enumerable.Empty())); + var f = new UmbracoDatabaseFactory(logger, new Lazy(() => new MapperCollection(Enumerable.Empty()))); var fs = new FileSystems(mock.Object, logger); var p = new ScopeProvider(f, fs, logger); @@ -47,13 +45,15 @@ namespace Umbraco.Tests.Components public void Boot1A() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var loader = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // 2 is Core and requires 4 // 3 is User - goes away with RuntimeLevel.Unknown // => reorder components accordingly - loader.Boot(TypeArray(), RuntimeLevel.Unknown); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -61,13 +61,15 @@ namespace Umbraco.Tests.Components public void Boot1B() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - var loader = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // 2 is Core and requires 4 // 3 is User - stays with RuntimeLevel.Run // => reorder components accordingly - loader.Boot(TypeArray(), RuntimeLevel.Run); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -75,12 +77,14 @@ namespace Umbraco.Tests.Components public void Boot2() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var loader = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // 21 is required by 20 // => reorder components accordingly - loader.Boot(TypeArray(), RuntimeLevel.Unknown); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -88,14 +92,16 @@ namespace Umbraco.Tests.Components public void Boot3() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var loader = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // i23 requires 22 // 24, 25 implement i23 // 25 required by i23 // => reorder components accordingly - loader.Boot(TypeArray(), RuntimeLevel.Unknown); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -103,15 +109,17 @@ namespace Umbraco.Tests.Components public void BrokenRequire() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); try { // 2 is Core and requires 4 // 4 is missing // => throw - thing.Boot(TypeArray < Component1, Component2, Component3>(), RuntimeLevel.Unknown); + components.Compose(); Assert.Fail("Expected exception."); } catch (Exception e) @@ -124,14 +132,16 @@ namespace Umbraco.Tests.Components public void BrokenRequired() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = TypeArray(); + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); // 2 is Core and requires 4 // 13 is required by 1 // 1 is missing // => reorder components accordingly - thing.Boot(TypeArray(), RuntimeLevel.Unknown); + components.Compose(); AssertTypeArray(TypeArray(), Composed); } @@ -142,11 +152,14 @@ namespace Umbraco.Tests.Components { m.Setup(x => x.TryGetInstance(It.Is(t => t == typeof (ISomeResource)))).Returns(() => new SomeResource()); }); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component1), typeof(Component5) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); Initialized.Clear(); - thing.Boot(new[] { typeof(Component1), typeof(Component5) }, RuntimeLevel.Unknown); + components.Compose(); + components.Initialize(); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component1), Composed[0]); Assert.AreEqual(typeof(Component5), Composed[1]); @@ -158,10 +171,12 @@ namespace Umbraco.Tests.Components public void Requires1() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component6), typeof(Component7), typeof(Component8) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component6), typeof(Component7), typeof(Component8) }, RuntimeLevel.Unknown); + components.Compose(); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component6), Composed[0]); Assert.AreEqual(typeof(Component8), Composed[1]); @@ -171,10 +186,12 @@ namespace Umbraco.Tests.Components public void Requires2A() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component9), typeof(Component2), typeof(Component4) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component9), typeof(Component2), typeof(Component4) }, RuntimeLevel.Unknown); + components.Compose(); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component4), Composed[0]); Assert.AreEqual(typeof(Component2), Composed[1]); @@ -185,10 +202,13 @@ namespace Umbraco.Tests.Components public void Requires2B() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - var thing = new BootLoader(container); + var types = new[] { typeof(Component9), typeof(Component2), typeof(Component4) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component9), typeof(Component2), typeof(Component4) }, RuntimeLevel.Run); + components.Compose(); + components.Initialize(); Assert.AreEqual(3, Composed.Count); Assert.AreEqual(typeof(Component4), Composed[0]); Assert.AreEqual(typeof(Component2), Composed[1]); @@ -199,24 +219,29 @@ namespace Umbraco.Tests.Components public void WeakDependencies() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component10) }; + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component10) }, RuntimeLevel.Unknown); + components.Compose(); Assert.AreEqual(1, Composed.Count); Assert.AreEqual(typeof(Component10), Composed[0]); - thing = new BootLoader(container); + types = new[] { typeof(Component11) }; + components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - Assert.Throws(() => thing.Boot(new[] { typeof(Component11) }, RuntimeLevel.Unknown)); + Assert.Throws(() => components.Compose()); - thing = new BootLoader(container); + types = new[] { typeof(Component2) }; + components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - Assert.Throws(() => thing.Boot(new[] { typeof(Component2) }, RuntimeLevel.Unknown)); + Assert.Throws(() => components.Compose()); - thing = new BootLoader(container); + types = new[] { typeof(Component12) }; + components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component12) }, RuntimeLevel.Unknown); + components.Compose(); Assert.AreEqual(1, Composed.Count); Assert.AreEqual(typeof(Component12), Composed[0]); } @@ -225,10 +250,12 @@ namespace Umbraco.Tests.Components public void DisableMissing() { var container = MockContainer(); + var composition = new Composition(container, RuntimeLevel.Unknown); - var thing = new BootLoader(container); + var types = new[] { typeof(Component6), typeof(Component8) }; // 8 disables 7 which is not in the list + var components = new Core.Components.Components(composition, types, Mock.Of()); Composed.Clear(); - thing.Boot(new[] { typeof(Component6), typeof(Component8) }, RuntimeLevel.Unknown); // 8 disables 7 which is not in the list + components.Compose(); Assert.AreEqual(2, Composed.Count); Assert.AreEqual(typeof(Component6), Composed[0]); Assert.AreEqual(typeof(Component8), Composed[1]); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 1bddbdfbb2..23914ef2bf 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -4,6 +4,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core.Composing; using Umbraco.Core; +using Umbraco.Core.Components; namespace Umbraco.Tests.Composing { @@ -11,6 +12,7 @@ namespace Umbraco.Tests.Composing public class CollectionBuildersTests { private IContainer _container; + private Composition _composition; [SetUp] public void Setup() @@ -18,6 +20,7 @@ namespace Umbraco.Tests.Composing Current.Reset(); _container = Current.Container = ContainerFactory.Create(); + _composition = new Composition(_container, RuntimeLevel.Run); } [TearDown] @@ -32,7 +35,7 @@ namespace Umbraco.Tests.Composing [Test] public void ContainsTypes() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -48,7 +51,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanClearBuilderBeforeCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -63,7 +66,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotClearBuilderOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -75,7 +78,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanAppendToBuilder() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); builder.Append(); builder.Append(); @@ -90,7 +93,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotAppendToBuilderOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); var col = builder.CreateCollection(); @@ -102,7 +105,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanAppendDuplicateToBuilderAndDeDuplicate() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); builder.Append(); builder.Append(); @@ -113,7 +116,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotAppendInvalidTypeToBUilder() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); //builder.Append(); // does not compile Assert.Throws(() => builder.Append(new[] { typeof (Resolved4) }) // throws @@ -123,7 +126,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanRemoveFromBuilder() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .Remove(); @@ -139,7 +142,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanRemoveMissingFromBuilder() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .Remove(); @@ -151,7 +154,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotRemoveFromBuilderOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -164,7 +167,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertIntoBuilder() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .Insert(); @@ -180,7 +183,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -193,7 +196,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertDuplicateIntoBuilderAndDeDuplicate() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .Insert(); @@ -205,7 +208,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertIntoEmptyBuilder() { - var builder = _container.RegisterCollectionBuilder(); + var builder = _composition.GetCollectionBuilder(); builder.Insert(); var col = builder.CreateCollection(); @@ -215,7 +218,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderAtWrongIndex() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -231,7 +234,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertIntoBuilderBefore() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .InsertBefore(); @@ -247,7 +250,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderBeforeOnceCollectionIsCreated() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append(); @@ -260,7 +263,7 @@ namespace Umbraco.Tests.Composing [Test] public void CanInsertDuplicateIntoBuilderBeforeAndDeDuplicate() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Append() .InsertBefore(); @@ -272,7 +275,7 @@ namespace Umbraco.Tests.Composing [Test] public void CannotInsertIntoBuilderBeforeMissing() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append(); Assert.Throws(() => @@ -283,7 +286,7 @@ namespace Umbraco.Tests.Composing [Test] public void ScopeBuilderCreatesScopedCollection() { - _container.RegisterCollectionBuilder() + _composition.GetCollectionBuilder() .Append() .Append(); @@ -303,7 +306,7 @@ namespace Umbraco.Tests.Composing [Test] public void TransientBuilderCreatesTransientCollection() { - _container.RegisterCollectionBuilder() + _composition.GetCollectionBuilder() .Append() .Append(); @@ -323,7 +326,7 @@ namespace Umbraco.Tests.Composing [Test] public void BuilderRespectsTypesOrder() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Append() .Insert() .InsertBefore(); @@ -335,7 +338,7 @@ namespace Umbraco.Tests.Composing [Test] public void ScopeBuilderRespectsContainerScope() { - _container.RegisterCollectionBuilder() + _composition.GetCollectionBuilder() .Append() .Append(); @@ -369,7 +372,7 @@ namespace Umbraco.Tests.Composing [Test] public void WeightedBuilderCreatesWeightedCollection() { - var builder = _container.RegisterCollectionBuilder() + var builder = _composition.GetCollectionBuilder() .Add() .Add(); @@ -434,20 +437,12 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilder : OrderedCollectionBuilderBase { - public TestCollectionBuilder(IContainer container) - : base(container) - { } - protected override TestCollectionBuilder This => this; } // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilderTransient : OrderedCollectionBuilderBase { - public TestCollectionBuilderTransient(IContainer container) - : base(container) - { } - protected override TestCollectionBuilderTransient This => this; protected override Lifetime CollectionLifetime => Lifetime.Transient; // transient @@ -456,10 +451,6 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilderScope : OrderedCollectionBuilderBase { - public TestCollectionBuilderScope(IContainer container) - : base(container) - { } - protected override TestCollectionBuilderScope This => this; protected override Lifetime CollectionLifetime => Lifetime.Scope; @@ -468,10 +459,6 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilderWeighted : WeightedCollectionBuilderBase { - public TestCollectionBuilderWeighted(IContainer container) - : base(container) - { } - protected override TestCollectionBuilderWeighted This => this; } diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index e0dde277f9..3d0a9602a2 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; namespace Umbraco.Tests.Composing @@ -33,8 +34,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypes() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() .Add() .Add() @@ -56,8 +58,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesProducers() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) .Add(() => new[] { typeof(TransientObject1) }); @@ -78,8 +81,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypesAndProducers() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() .Add() .Add() @@ -101,8 +105,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderThrowsOnIllegalTypes() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() // illegal, does not implement the interface! @@ -122,8 +127,9 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderCanExcludeTypes() { var container = CreateContainer(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2), typeof(TransientObject1) }) .Exclude(); @@ -162,10 +168,6 @@ namespace Umbraco.Tests.Composing // ReSharper disable once ClassNeverInstantiated.Local private class TestCollectionBuilder : LazyCollectionBuilderBase { - public TestCollectionBuilder(IContainer container) - : base(container) - { } - protected override TestCollectionBuilder This => this; protected override Lifetime CollectionLifetime => Lifetime.Transient; // transient diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 236d92b94e..8893b61fde 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Xml; using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core._Legacy.PackageActions; @@ -14,8 +16,9 @@ namespace Umbraco.Tests.Composing public void PackageActionCollectionBuilderWorks() { var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); var actions = Current.PackageActions; diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index fd48834cfe..30dfabbbdc 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -52,7 +52,7 @@ namespace Umbraco.Tests.Integration Container.Register(_ => new TestServerRegistrar()); // localhost-only Container.RegisterSingleton(); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add() .Add() .Add(); diff --git a/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs b/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs index ae72d996a8..f4a33f735d 100644 --- a/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs +++ b/src/Umbraco.Tests/Misc/ApplicationUrlHelperTests.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Misc [Test] public void NoApplicationUrlByDefault() { - var state = new RuntimeState(Mock.Of(), new Lazy(Mock.Of), new Lazy(Mock.Of), Mock.Of(), Mock.Of()); + var state = new RuntimeState(Mock.Of(), Mock.Of(), Mock.Of(), new Lazy(), new Lazy()); Assert.IsNull(state.ApplicationUrl); } @@ -46,10 +46,7 @@ namespace Umbraco.Tests.Misc var registrar = new Mock(); registrar.Setup(x => x.GetCurrentServerUmbracoApplicationUrl()).Returns("http://server1.com/umbraco"); - var state = new RuntimeState( - Mock.Of(), - new Lazy(() => registrar.Object), - new Lazy(Mock.Of), settings, globalConfig.Object); + var state = new RuntimeState(Mock.Of(), settings, globalConfig.Object, new Lazy(), new Lazy(() => registrar.Object)); state.EnsureApplicationUrl(); @@ -72,7 +69,7 @@ namespace Umbraco.Tests.Misc - var state = new RuntimeState(Mock.Of(), new Lazy(Mock.Of), new Lazy(Mock.Of), settings, globalConfig.Object); + var state = new RuntimeState(Mock.Of(), settings, globalConfig.Object, new Lazy(), new Lazy(() => Mock.Of())); state.EnsureApplicationUrl(); @@ -147,7 +144,5 @@ namespace Umbraco.Tests.Misc Assert.AreEqual("httpx://whatever.com/umbraco", url); } - - } } diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index 2bf8aeead3..87698db400 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -31,7 +31,7 @@ namespace Umbraco.Tests.Models.Mapping Container.Register(_ => manifestBuilder); Func> typeListProducerList = Enumerable.Empty; - Container.GetInstance() + Composition.GetCollectionBuilder() .Clear() .Add(typeListProducerList); } diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs index 788ee597dd..d45016ba11 100644 --- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs +++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Persistence _sqlCeSyntaxProvider = new SqlCeSyntaxProvider(); _sqlSyntaxProviders = new[] { (ISqlSyntaxProvider) _sqlCeSyntaxProvider }; _logger = Mock.Of(); - _databaseFactory = new UmbracoDatabaseFactory(_sqlSyntaxProviders, _logger, Mock.Of()); + _databaseFactory = new UmbracoDatabaseFactory(_logger, new Lazy(() => Mock.Of())); } [TearDown] @@ -76,7 +76,7 @@ namespace Umbraco.Tests.Persistence } // re-create the database factory and database context with proper connection string - _databaseFactory = new UmbracoDatabaseFactory(connString, Constants.DbProviderNames.SqlCe, _sqlSyntaxProviders, _logger, Mock.Of()); + _databaseFactory = new UmbracoDatabaseFactory(connString, Constants.DbProviderNames.SqlCe, _logger, new Lazy(() => Mock.Of())); // create application context //var appCtx = new ApplicationContext( diff --git a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs index bff43d5ea8..6aba8187f2 100644 --- a/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs +++ b/src/Umbraco.Tests/Persistence/FaultHandling/ConnectionRetryTest.cs @@ -19,8 +19,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling { const string connectionString = @"server=.\SQLEXPRESS;database=EmptyForTest;user id=x;password=umbraco"; const string providerName = Constants.DbProviderNames.SqlServer; - var sqlSyntax = new[] { new SqlServerSyntaxProvider(new Lazy(() => null)) }; - var factory = new UmbracoDatabaseFactory(connectionString, providerName, sqlSyntax, Mock.Of(), Mock.Of()); + var factory = new UmbracoDatabaseFactory(connectionString, providerName, Mock.Of(), new Lazy(() => Mock.Of())); using (var database = factory.CreateDatabase()) { @@ -34,8 +33,7 @@ namespace Umbraco.Tests.Persistence.FaultHandling { const string connectionString = @"server=.\SQLEXPRESS;database=EmptyForTest;user id=umbraco;password=umbraco"; const string providerName = Constants.DbProviderNames.SqlServer; - var sqlSyntax = new[] { new SqlServerSyntaxProvider(new Lazy(() => null)) }; - var factory = new UmbracoDatabaseFactory(connectionString, providerName, sqlSyntax, Mock.Of(), Mock.Of()); + var factory = new UmbracoDatabaseFactory(connectionString, providerName, Mock.Of(), new Lazy(() => Mock.Of())); using (var database = factory.CreateDatabase()) { diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index 0e8f1e9e16..1f0036d874 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -670,7 +670,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void AliasRegexTest() { - var regex = new SqlServerSyntaxProvider(new Lazy(() => null)).AliasRegex; + var regex = new SqlServerSyntaxProvider().AliasRegex; Assert.AreEqual(@"(\[\w+]\.\[\w+])\s+AS\s+(\[\w+])", regex.ToString()); const string sql = "SELECT [table].[column1] AS [alias1], [table].[column2] AS [alias2] FROM [table];"; var matches = regex.Matches(sql); diff --git a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs index df842dc43c..557de9eb11 100644 --- a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs +++ b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs @@ -74,7 +74,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, [Test] public void Format_SqlServer_NonClusteredIndexDefinition_AddsNonClusteredDirective() { - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var indexDefinition = CreateIndexDefinition(); indexDefinition.IndexType = IndexTypes.NonClustered; @@ -86,7 +86,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, [Test] public void Format_SqlServer_NonClusteredIndexDefinition_UsingIsClusteredFalse_AddsClusteredDirective() { - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var indexDefinition = CreateIndexDefinition(); indexDefinition.IndexType = IndexTypes.Clustered; @@ -99,7 +99,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, public void CreateIndexBuilder_SqlServer_NonClustered_CreatesNonClusteredIndex() { var logger = Mock.Of(); - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var db = new TestDatabase(DatabaseType.SqlServer2005, sqlSyntax); var context = new MigrationContext(db, logger); @@ -120,7 +120,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, public void CreateIndexBuilder_SqlServer_Unique_CreatesUniqueNonClusteredIndex() { var logger = Mock.Of(); - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var db = new TestDatabase(DatabaseType.SqlServer2005, sqlSyntax); var context = new MigrationContext(db, logger); @@ -141,7 +141,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, public void CreateIndexBuilder_SqlServer_Unique_CreatesUniqueNonClusteredIndex_Multi_Columnn() { var logger = Mock.Of(); - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var db = new TestDatabase(DatabaseType.SqlServer2005, sqlSyntax); var context = new MigrationContext(db, logger); @@ -162,7 +162,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine, public void CreateIndexBuilder_SqlServer_Clustered_CreatesClusteredIndex() { var logger = Mock.Of(); - var sqlSyntax = new SqlServerSyntaxProvider(new Lazy(() => null)); + var sqlSyntax = new SqlServerSyntaxProvider(); var db = new TestDatabase(DatabaseType.SqlServer2005, sqlSyntax); var context = new MigrationContext(db, logger); diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 7e56ad61a8..de27c30b1d 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json; using NUnit.Framework; using Newtonsoft.Json.Linq; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -67,8 +68,9 @@ namespace Umbraco.Tests.PropertyEditors try { var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); - container.RegisterCollectionBuilder(); + composition.GetCollectionBuilder(); var logger = Mock.Of(); var scheme = Mock.Of(); diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index c0ae68d7d5..0e65f5723f 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -4,6 +4,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -172,9 +173,9 @@ namespace Umbraco.Tests.Published { Current.Reset(); var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); - - Current.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append() .Append(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index a1df9e3720..80fb02ec0f 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -23,10 +23,8 @@ namespace Umbraco.Tests.PublishedContent // fixme - what about the if (PropertyValueConvertersResolver.HasCurrent == false) ?? // can we risk double - registering and then, what happens? - var builder = Container.TryGetInstance() - ?? Container.RegisterCollectionBuilder(); - - builder.Clear() + Composition.GetCollectionBuilder() + .Clear() .Append() .Append() .Append(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs index e9d133c901..9d603a9569 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedMediaTests.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Container.GetInstance() + Composition.GetCollectionBuilder() .Clear() .Append(); } diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index e26db55ace..7fef0147e7 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -32,7 +32,8 @@ namespace Umbraco.Tests.Routing //create the module var logger = Mock.Of(); var globalSettings = TestObjects.GetGlobalSettings(); - var runtime = new RuntimeState(logger, new Lazy(), new Lazy(), Mock.Of(), globalSettings); + var runtime = new RuntimeState(logger, Mock.Of(), globalSettings, + new Lazy(), new Lazy()); _module = new UmbracoInjectedModule ( diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 68746350f6..907de9ccde 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -74,9 +74,11 @@ namespace Umbraco.Tests.Runtimes return new DebugDiagnosticsLogger(); } - public override void Compose(IContainer container) + public override void Compose(Composition composition) { - base.Compose(container); + base.Compose(composition); + + var container = composition.Container; // the application's profiler and profiling logger are // registered by CoreRuntime.Compose() but can be @@ -100,7 +102,7 @@ namespace Umbraco.Tests.Runtimes // pretend we have the proper migration // else BootFailedException because our mock IUmbracoDatabaseFactory does not provide databases - protected override bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) + protected override bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory) { return true; } @@ -122,7 +124,7 @@ namespace Umbraco.Tests.Runtimes // runs with only one single component // UmbracoCoreComponent will be force-added too // and that's it - protected override IEnumerable GetComponentTypes() + protected override IEnumerable GetComponentTypes(TypeLoader typeLoader) { return new[] { typeof(TestComponent) }; } diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 56987416a4..486cf55769 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -3,6 +3,7 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.IO; @@ -30,11 +31,12 @@ namespace Umbraco.Tests.Scoping DoThing3 = null; var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); _testObjects = new TestObjects(container); Current.Container.RegisterSingleton(factory => new FileSystems(container, factory.TryGetInstance())); - Current.Container.RegisterCollectionBuilder(); + composition.GetCollectionBuilder(); SettingsForTests.Reset(); // ensure we have configuration } diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 9308e9bbaf..b25b7eed42 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Scoping // so doing all this mess Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add(f => f.TryGetInstance().GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 4f6fafbbbf..3d281575fb 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Scoping // so doing all this mess Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add(f => f.TryGetInstance().GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 65bc5762c7..2cfadb9408 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Scoping // so doing all this mess Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add(f => f.TryGetInstance().GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 489be00a14..31f0f0308b 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -57,8 +57,7 @@ namespace Umbraco.Tests.Services { base.Compose(); - // fixme - do it differently - Container.Register(factory => factory.GetInstance().TextService); + Container.RegisterSingleton(factory => Mock.Of()); } /// diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index c28d4f7955..b934686c87 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Services // pfew - see note in ScopedNuCacheTests? Container.RegisterSingleton(); Container.RegisterSingleton(f => Mock.Of()); - Container.RegisterCollectionBuilder() + Composition.GetCollectionBuilder() .Add(f => f.TryGetInstance().GetCacheRefreshers()); } @@ -770,4 +770,4 @@ namespace Umbraco.Tests.Services "{'properties':{'value11':[{'culture':'','seg':'','val':'v11'}],'value12':[{'culture':'','seg':'','val':'v12'}],'value31':[{'culture':'','seg':'','val':'v31'}],'value32':[{'culture':'','seg':'','val':'v32'}]},'cultureData':"); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index b9b410206e..05793e85dd 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -49,7 +49,7 @@ namespace Umbraco.Tests.Services.Importing // pollute everything, they are ignored by the type finder and explicitely // added to the editors collection - Container.GetInstance() + Composition.GetCollectionBuilder() .Add() .Add(); } diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 4314af38b5..c8a2219c3f 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -3,6 +3,7 @@ using NPoco; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Components; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; @@ -33,6 +34,7 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); var container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(container, RuntimeLevel.Run); container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); @@ -44,7 +46,7 @@ namespace Umbraco.Tests.TestHelpers false); container.RegisterInstance(pluginManager); - container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => Current.TypeLoader.GetAssignedMapperTypes()); Mappers = container.GetInstance(); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 9f16141c2f..c965a71a70 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -37,22 +37,6 @@ namespace Umbraco.Tests.TestHelpers _container = container; } - /// - /// Gets the default ISqlSyntaxProvider objects. - /// - /// A logger. - /// A (lazy) scope provider. - /// The default ISqlSyntaxProvider objects. - public IEnumerable GetDefaultSqlSyntaxProviders(ILogger logger, Lazy lazyScopeProvider = null) - { - return new ISqlSyntaxProvider[] - { - new MySqlSyntaxProvider(logger), - new SqlCeSyntaxProvider(), - new SqlServerSyntaxProvider(lazyScopeProvider ?? new Lazy(() => null)) - }; - } - /// /// Gets an UmbracoDatabase. /// @@ -77,7 +61,7 @@ namespace Umbraco.Tests.TestHelpers /// that can begin a transaction. public UmbracoDatabase GetUmbracoSqlServerDatabase(ILogger logger) { - var syntax = new SqlServerSyntaxProvider(new Lazy(() => null)); // do NOT try to get the server's version! + var syntax = new SqlServerSyntaxProvider(); // do NOT try to get the server's version! var connection = GetDbConnection(); var sqlContext = new SqlContext(syntax, DatabaseType.SqlServer2008, Mock.Of()); return new UmbracoDatabase(connection, sqlContext, logger); @@ -241,7 +225,7 @@ namespace Umbraco.Tests.TestHelpers //mappersBuilder.AddCore(); //var mappers = mappersBuilder.CreateCollection(); var mappers = Current.Container.GetInstance(); - databaseFactory = new UmbracoDatabaseFactory(Constants.System.UmbracoConnectionName, GetDefaultSqlSyntaxProviders(logger), logger, mappers); + databaseFactory = new UmbracoDatabaseFactory(Constants.System.UmbracoConnectionName, logger, new Lazy(() => mappers)); } fileSystems = fileSystems ?? new FileSystems(Current.Container, logger); diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index d0dfcc8c2e..fa61381eed 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -76,7 +76,7 @@ namespace Umbraco.Tests.TestHelpers Container.Register(factory => PublishedSnapshotService); Container.Register(factory => DefaultCultureAccessor); - Container.GetInstance() + Composition.GetCollectionBuilder() .Clear() .Add(f => f.GetInstance().GetDataEditors()); @@ -85,10 +85,9 @@ namespace Umbraco.Tests.TestHelpers if (Options.Database == UmbracoTestOptions.Database.None) return TestObjects.GetDatabaseFactoryMock(); - var sqlSyntaxProviders = new[] { new SqlCeSyntaxProvider() }; var logger = f.GetInstance(); var mappers = f.GetInstance(); - var factory = new UmbracoDatabaseFactory(GetDbConnectionString(), GetDbProviderName(), sqlSyntaxProviders, logger, mappers); + var factory = new UmbracoDatabaseFactory(GetDbConnectionString(), GetDbProviderName(), logger, new Lazy(() => mappers)); factory.ResetForTests(); return factory; }); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 45a4bc5917..ee5768d499 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -76,6 +76,8 @@ namespace Umbraco.Tests.Testing // test feature, and no test "base" class should be. only actual test feature classes // should be marked with that attribute. + protected Composition Composition { get; private set; } + protected IContainer Container { get; private set; } protected UmbracoTestAttribute Options { get; private set; } @@ -116,6 +118,7 @@ namespace Umbraco.Tests.Testing Reset(); Container = Current.Container = ContainerFactory.Create(); + Composition = new Composition(Container, RuntimeLevel.Run); TestObjects = new TestObjects(Container); @@ -189,7 +192,7 @@ namespace Umbraco.Tests.Testing // web Container.Register(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); Container.RegisterSingleton(); - Container.RegisterCollectionBuilder(); + Composition.GetCollectionBuilder(); Container.Register(); Container.Register(); } @@ -202,14 +205,14 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(f => runtimeStateMock.Object); // ah... - Container.RegisterCollectionBuilder(); - Container.RegisterCollectionBuilder(); + Composition.GetCollectionBuilder(); + Composition.GetCollectionBuilder(); Container.RegisterSingleton(); Container.RegisterSingleton(); // register empty content apps collection - Container.RegisterCollectionBuilder(); + Composition.GetCollectionBuilder(); } protected virtual void ComposeCacheHelper() @@ -307,20 +310,17 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(); // register application stuff (database factory & context, services...) - Container.RegisterCollectionBuilder() - .AddCore(); + Composition.GetCollectionBuilder() + .AddCoreMappers(); Container.RegisterSingleton(_ => new TransientEventMessagesFactory()); - var sqlSyntaxProviders = TestObjects.GetDefaultSqlSyntaxProviders(Logger); - Container.RegisterSingleton(_ => sqlSyntaxProviders.OfType().First()); Container.RegisterSingleton(f => new UmbracoDatabaseFactory( Constants.System.UmbracoConnectionName, - sqlSyntaxProviders, Logger, - Mock.Of())); + new Lazy(() => Mock.Of()))); Container.RegisterSingleton(f => f.TryGetInstance().SqlContext); - Container.RegisterCollectionBuilder(); // empty + Composition.GetCollectionBuilder(); // empty Container.RegisterSingleton(factory => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); @@ -333,12 +333,11 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(); // somehow property editor ends up wanting this - Container.RegisterCollectionBuilder(); + Composition.GetCollectionBuilder(); Container.RegisterSingleton(); // note - don't register collections, use builders - Container.RegisterCollectionBuilder(); - var temp = Container.GetInstance(); + Composition.GetCollectionBuilder(); Container.RegisterSingleton(); Container.RegisterSingleton(); } diff --git a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs index 027a3fcd9b..8400e02271 100644 --- a/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs +++ b/src/Umbraco.Web/Actions/ActionCollectionBuilder.cs @@ -7,10 +7,6 @@ namespace Umbraco.Web.Actions { internal class ActionCollectionBuilder : LazyCollectionBuilderBase { - public ActionCollectionBuilder(IContainer container) - : base(container) - { } - protected override ActionCollectionBuilder This => this; protected override IEnumerable CreateItems() diff --git a/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs b/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs index 6fcaea87a3..8c47e0f640 100644 --- a/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs +++ b/src/Umbraco.Web/ContentApps/ContentAppDefinitionCollectionBuilder.cs @@ -9,10 +9,6 @@ namespace Umbraco.Web.ContentApps { public class ContentAppDefinitionCollectionBuilder : OrderedCollectionBuilderBase { - public ContentAppDefinitionCollectionBuilder(IContainer container) - : base(container) - { } - protected override ContentAppDefinitionCollectionBuilder This => this; // need to inject dependencies in the collection, so override creation diff --git a/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs b/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs index 3189f2e71f..b3b7bab1a5 100644 --- a/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs +++ b/src/Umbraco.Web/Editors/EditorValidatorCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.Editors { internal class EditorValidatorCollectionBuilder : LazyCollectionBuilderBase { - public EditorValidatorCollectionBuilder(IContainer container) - : base(container) - { } - protected override EditorValidatorCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs index 76a93fe217..b78c188660 100644 --- a/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs +++ b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs @@ -5,10 +5,6 @@ namespace Umbraco.Web.HealthCheck { internal class HealthCheckNotificationMethodCollectionBuilder : LazyCollectionBuilderBase { - public HealthCheckNotificationMethodCollectionBuilder(IContainer container) - : base(container) - { } - protected override HealthCheckNotificationMethodCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs index 7e600d9238..e616ba49ae 100644 --- a/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs +++ b/src/Umbraco.Web/HealthCheck/HeathCheckCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.HealthCheck { public class HealthCheckCollectionBuilder : LazyCollectionBuilderBase { - public HealthCheckCollectionBuilder(IContainer container) - : base(container) - { } - protected override HealthCheckCollectionBuilder This => this; // note: in v7 they were per-request, not sure why? diff --git a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs b/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs index 4ec48bac3f..2c4182beac 100644 --- a/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs +++ b/src/Umbraco.Web/Mvc/FilteredControllerFactoryCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.Mvc { public class FilteredControllerFactoryCollectionBuilder : OrderedCollectionBuilderBase { - public FilteredControllerFactoryCollectionBuilder(IContainer container) - : base(container) - { } - protected override FilteredControllerFactoryCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs b/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs index 47186dbb74..401a7daf43 100644 --- a/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs +++ b/src/Umbraco.Web/Routing/ContentFinderCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.Routing { public class ContentFinderCollectionBuilder : OrderedCollectionBuilderBase { - public ContentFinderCollectionBuilder(IContainer container) - : base(container) - { } - protected override ContentFinderCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs b/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs index d66a7554b8..06f2728f4c 100644 --- a/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs +++ b/src/Umbraco.Web/Routing/UrlProviderCollectionBuilder.cs @@ -4,10 +4,6 @@ namespace Umbraco.Web.Routing { public class UrlProviderCollectionBuilder : OrderedCollectionBuilderBase { - public UrlProviderCollectionBuilder(IContainer container) - : base(container) - { } - protected override UrlProviderCollectionBuilder This => this; } } diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 342e4aede4..52bf980853 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -1,5 +1,6 @@ using System.Web; using Umbraco.Core.Cache; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; @@ -51,21 +52,23 @@ namespace Umbraco.Web.Runtime } /// - public override void Compose(IContainer container) + public override void Compose(Composition composition) { + base.Compose(composition); + + var container = composition.Container; + // some components may want to initialize with the UmbracoApplicationBase // well, they should not - we should not do this // TODO remove this eventually. container.RegisterInstance(_umbracoApplication); - base.Compose(container); + } - container.Register(); + #region Getters - // replace CoreRuntime's IProfiler registration - container.RegisterSingleton(_ => _webProfiler); + protected override IProfiler GetProfiler() => new WebProfiler(); - // replace CoreRuntime's CacheHelper registration - container.RegisterSingleton(_ => new CacheHelper( + protected override CacheHelper GetAppCaches() => new CacheHelper( // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), @@ -75,26 +78,7 @@ namespace Umbraco.Web.Runtime new IsolatedRuntimeCache(type => // we need to have the dep clone runtime cache provider to ensure // all entities are cached properly (cloned in and cloned out) - new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())))); - - container.RegisterSingleton(); // required for hybrid accessors - } - - #region Getters - - //protected override IProfiler GetProfiler() => new WebProfiler(); - - //protected override CacheHelper GetApplicationCache() => new CacheHelper( - // // we need to have the dep clone runtime cache provider to ensure - // // all entities are cached properly (cloned in and cloned out) - // new DeepCloneRuntimeCacheProvider(new HttpRuntimeCacheProvider(HttpRuntime.Cache)), - // new StaticCacheProvider(), - // // we need request based cache when running in web-based context - // new HttpRequestCacheProvider(), - // new IsolatedRuntimeCache(type => - // // we need to have the dep clone runtime cache provider to ensure - // // all entities are cached properly (cloned in and cloned out) - // new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); + new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))); #endregion } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 24a84905e3..3705eea086 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -64,109 +64,115 @@ namespace Umbraco.Web.Runtime { base.Compose(composition); - composition.Container.ComposeWebMappingProfiles(); + var container = composition.Container; + + container.Register(); + + container.RegisterSingleton(); // required for hybrid accessors + + container.ComposeWebMappingProfiles(); //register the install components //NOTE: i tried to not have these registered if we weren't installing or upgrading but post install when the site restarts //it still needs to use the install controller so we can't do that - composition.Container.ComposeInstaller(); + container.ComposeInstaller(); // register membership stuff - composition.Container.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); - composition.Container.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance())); - composition.Container.Register(); + container.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); + container.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance())); + container.Register(); // register accessors for cultures - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); - var typeLoader = composition.Container.GetInstance(); - var logger = composition.Container.GetInstance(); - var proflog = composition.Container.GetInstance(); + var typeLoader = container.GetInstance(); + var logger = container.GetInstance(); + var proflog = container.GetInstance(); // register the http context and umbraco context accessors // we *should* use the HttpContextUmbracoContextAccessor, however there are cases when // we have no http context, eg when booting Umbraco or in background threads, so instead // let's use an hybrid accessor that can fall back to a ThreadStatic context. - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request - composition.Container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); + container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // we should stop injecting UmbracoContext and always inject IUmbracoContextAccessor, however at the moment // there are tons of places (controllers...) which require UmbracoContext in their ctor - so let's register // a way to inject the UmbracoContext - and register it per-request to be more efficient //TODO: stop doing this - composition.Container.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); + container.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); // register the umbraco helper - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // register distributed cache - composition.Container.RegisterSingleton(f => new DistributedCache()); + container.RegisterSingleton(f => new DistributedCache()); // replace some services - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); - composition.Container.RegisterSingleton(factory => ExamineManager.Instance); + container.RegisterSingleton(factory => ExamineManager.Instance); // configure the container for web - composition.Container.ConfigureForWeb(); - composition.Container.ComposeMvcControllers(typeLoader, GetType().Assembly); - composition.Container.ComposeApiControllers(typeLoader, GetType().Assembly); + container.ConfigureForWeb(); + container.ComposeMvcControllers(typeLoader, GetType().Assembly); + container.ComposeApiControllers(typeLoader, GetType().Assembly); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?! - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); - composition.Container.RegisterCollectionBuilder(); + composition.GetCollectionBuilder(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // set the default RenderMvcController Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); var surfaceControllerTypes = new SurfaceControllerTypeCollection(typeLoader.GetSurfaceControllers()); - composition.Container.RegisterInstance(surfaceControllerTypes); + container.RegisterInstance(surfaceControllerTypes); var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(typeLoader.GetUmbracoApiControllers()); - composition.Container.RegisterInstance(umbracoApiControllerTypes); + container.RegisterInstance(umbracoApiControllerTypes); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be // discovered when CoreBootManager configures the converters. We HAVE to remove one of them // here because there cannot be two converters for one property editor - and we want the full // RteMacroRenderingValueConverter that converts macros, etc. So remove TinyMceValueConverter. // (the limited one, defined in Core, is there for tests) - same for others - composition.Container.GetInstance() + container.GetInstance() .Remove() .Remove() .Remove(); // add all known factories, devs can then modify this list on application // startup either by binding to events or in their own global.asax - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append(); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append() .Append() .Append(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() // all built-in finders in the correct order, // devs can then modify this list on application startup .Append() @@ -176,32 +182,32 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // register *all* checks, except those marked [HideFromTypeFinder] of course - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); // auto-register views - composition.Container.RegisterAuto(typeof(UmbracoViewPage<>)); + container.RegisterAuto(typeof(UmbracoViewPage<>)); // register published router - composition.Container.RegisterSingleton(); - composition.Container.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); + container.RegisterSingleton(); + container.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); // register preview SignalR hub - composition.Container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); + container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); // register properties fallback - composition.Container.RegisterSingleton(); + container.RegisterSingleton(); // register known content apps - composition.Container.RegisterCollectionBuilder() + composition.GetCollectionBuilder() .Append() .Append() .Append(); diff --git a/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs b/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs index e64738329b..51f4b13f0a 100644 --- a/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs +++ b/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs @@ -1,24 +1,10 @@ using Umbraco.Core.Composing; -using Umbraco.Core.Services; using Umbraco.Web.Trees; namespace Umbraco.Web.Search { internal class SearchableTreeCollectionBuilder : LazyCollectionBuilderBase { - private readonly IApplicationTreeService _treeService; - - public SearchableTreeCollectionBuilder(IContainer container, IApplicationTreeService treeService) - : base(container) - { - _treeService = treeService; - } - protected override SearchableTreeCollectionBuilder This => this; - - public override SearchableTreeCollection CreateCollection() - { - return new SearchableTreeCollection(CreateItems(), _treeService); - } } } diff --git a/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs b/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs index f521b91f26..c5d7f7eadd 100644 --- a/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs +++ b/src/Umbraco.Web/Tour/TourFilterCollectionBuilder.cs @@ -14,13 +14,6 @@ namespace Umbraco.Web.Tour { private readonly HashSet _instances = new HashSet(); - /// - /// Initializes a new instance of the class. - /// - public TourFilterCollectionBuilder(IContainer container) - : base(container) - { } - /// protected override IEnumerable CreateItems(/*params object[] args*/) {