From 5b111f96291e3d8b6046a82daf8febe99b6d225d Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 27 Nov 2018 10:37:33 +0100 Subject: [PATCH] More composition simplification --- .../Composers/ConfigurationComposer.cs | 9 +- .../Composers/CoreMappingProfilesComposer.cs | 6 +- .../Composers/FileSystemsComposer.cs | 10 +-- .../Composers/RepositoriesComposer.cs | 9 +- .../Composing/Composers/ServicesComposer.cs | 7 +- src/Umbraco.Core/Composing/Current.cs | 6 +- src/Umbraco.Core/IRuntime.cs | 5 ++ .../ValueConverters/GridValueConverter.cs | 2 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 51 +++++------ .../Runtime/CoreRuntimeComponent.cs | 25 ++++-- .../Sync/DatabaseServerMessenger.cs | 6 +- src/Umbraco.Examine/UmbracoContentIndexer.cs | 4 +- src/Umbraco.Examine/UmbracoExamineIndexer.cs | 14 +-- src/Umbraco.Examine/UmbracoMemberIndexer.cs | 2 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 4 +- src/Umbraco.Tests/Models/ContentTests.cs | 2 +- .../Runtimes/CoreRuntimeTests.cs | 85 ++++++++++++------- .../Scoping/ScopeFileSystemsTests.cs | 2 +- .../Services/Importing/PackageImportTests.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 9 +- .../Composers/ControllersComposer.cs | 13 ++- .../Composing/Composers/InstallerComposer.cs | 9 +- .../Composers/WebMappingProfilesComposer.cs | 7 +- src/Umbraco.Web/Composing/Current.cs | 4 +- src/Umbraco.Web/Macros/MacroRenderer.cs | 10 +-- src/Umbraco.Web/Runtime/WebRuntime.cs | 1 - .../Runtime/WebRuntimeComponent.cs | 9 +- src/Umbraco.Web/Suspendable.cs | 12 +-- src/Umbraco.Web/UI/Controls/UmbracoControl.cs | 3 +- .../UI/Controls/UmbracoUserControl.cs | 6 +- src/Umbraco.Web/UI/Pages/BasePage.cs | 5 +- src/Umbraco.Web/UmbracoHttpHandler.cs | 5 +- src/Umbraco.Web/UmbracoWebService.cs | 2 +- 33 files changed, 199 insertions(+), 147 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs index 4e8f2ec65c..08b88dfc04 100644 --- a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Configuration; +using Umbraco.Core.Components; +using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Core.Composing.Composers @@ -8,8 +9,10 @@ namespace Umbraco.Core.Composing.Composers /// public static class ConfigurationComposer { - public static IContainer ComposeConfiguration(this IContainer container) + public static Composition ComposeConfiguration(this Composition composition) { + var container = composition.Container; + container.Register(factory => UmbracoConfig.For.UmbracoSettings()); container.Register(factory => factory.GetInstance().Content); container.Register(factory => factory.GetInstance().Templates); @@ -18,7 +21,7 @@ namespace Umbraco.Core.Composing.Composers // fixme - other sections we need to add? - return container; + return composition; } } } diff --git a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs index fbb653b3e9..38b15b6084 100644 --- a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Umbraco.Core.Components; using Umbraco.Core.Models.Identity; namespace Umbraco.Core.Composing.Composers @@ -6,10 +7,11 @@ namespace Umbraco.Core.Composing.Composers { public static class CoreMappingProfilesComposer { - public static IContainer ComposeCoreMappingProfiles(this IContainer container) + public static Composition ComposeCoreMappingProfiles(this Composition composition) { + var container = composition.Container; container.Register(); - return container; + return composition; } } } diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index 313e4ce97c..a1895df4e6 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -1,6 +1,4 @@ -using System; -using System.Configuration; -using Umbraco.Core.Configuration; +using Umbraco.Core.Components; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; @@ -67,8 +65,10 @@ namespace Umbraco.Core.Composing.Composers * */ - public static IContainer ComposeFileSystems(this IContainer container) + public static Composition ComposeFileSystems(this Composition composition) { + var container = composition.Container; + // register FileSystems, which manages all filesystems // it needs to be registered (not only the interface) because it provides additional // functionality eg for scoping, and is injected in the scope provider - whereas the @@ -85,7 +85,7 @@ namespace Umbraco.Core.Composing.Composers container.RegisterFileSystem( factory => new PhysicalFileSystem("~/media")); - return container; + return composition; } } } diff --git a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs index f44afe394f..d0fdf63fb9 100644 --- a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Components; +using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; namespace Umbraco.Core.Composing.Composers @@ -8,8 +9,10 @@ namespace Umbraco.Core.Composing.Composers /// public static class RepositoriesComposer { - public static IContainer ComposeRepositories(this IContainer container) + public static Composition ComposeRepositories(this Composition composition) { + var container = composition.Container; + // repositories container.RegisterSingleton(); container.RegisterSingleton(); @@ -47,7 +50,7 @@ namespace Umbraco.Core.Composing.Composers container.RegisterSingleton(); container.RegisterSingleton(); - return container; + return composition; } } } diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index 16b824e481..2db718f0ce 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using Umbraco.Core.Cache; +using Umbraco.Core.Components; using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -12,8 +13,10 @@ namespace Umbraco.Core.Composing.Composers { public static class ServicesComposer { - public static IContainer ComposeServices(this IContainer container) + public static Composition ComposeServices(this Composition composition) { + var container = composition.Container; + // register a transient messages factory, which will be replaced by the web // boot manager when running in a web context container.RegisterSingleton(); @@ -60,7 +63,7 @@ namespace Umbraco.Core.Composing.Composers container.RegisterSingleton(); container.RegisterSingleton(); - return container; + return composition; } private static LocalizedTextServiceFileSources SourcesFactory(IContainer container) diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index 7792b31dc1..17c8fcd48b 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -31,7 +31,7 @@ namespace Umbraco.Core.Composing private static IShortStringHelper _shortStringHelper; private static ILogger _logger; private static IProfiler _profiler; - private static ProfilingLogger _profilingLogger; + private static IProfilingLogger _profilingLogger; private static IPublishedValueFallback _publishedValueFallback; /// @@ -91,8 +91,8 @@ namespace Umbraco.Core.Composing => _profiler ?? (_profiler = _container?.TryGetInstance() ?? new LogProfiler(Logger)); - public static ProfilingLogger ProfilingLogger - => _profilingLogger ?? (_profilingLogger = _container?.TryGetInstance()) + public static IProfilingLogger ProfilingLogger + => _profilingLogger ?? (_profilingLogger = _container?.TryGetInstance()) ?? new ProfilingLogger(Logger, Profiler); public static IRuntimeState RuntimeState diff --git a/src/Umbraco.Core/IRuntime.cs b/src/Umbraco.Core/IRuntime.cs index f11bafbf2f..12a189b781 100644 --- a/src/Umbraco.Core/IRuntime.cs +++ b/src/Umbraco.Core/IRuntime.cs @@ -13,6 +13,11 @@ namespace Umbraco.Core /// The application container. void Boot(IContainer container); + /// + /// Gets the runtime state. + /// + IRuntimeState State { get; } + /// /// Terminates the runtime. /// diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs index 2131764ad6..d64a89dd07 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs @@ -49,7 +49,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters //TODO: Change all singleton access to use ctor injection in v8!!! //TODO: That would mean that property value converters would need to be request lifespan, hrm.... var gridConfig = UmbracoConfig.For.GridConfig( - Current.ProfilingLogger.Logger, + Current.ProfilingLogger, Current.ApplicationCache.RuntimeCache, new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)), new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config)), diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 2ae7c66136..d4c7d80c3d 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -6,7 +6,6 @@ using System.Web; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.Composers; using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; using Umbraco.Core.IO; @@ -15,7 +14,6 @@ using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Scoping; using Umbraco.Core.Services.Implement; using Umbraco.Core.Sync; @@ -30,6 +28,7 @@ namespace Umbraco.Core.Runtime { private Components.Components _components; private RuntimeState _state; + private IContainer _container; /// /// Gets the logger. @@ -41,11 +40,14 @@ namespace Umbraco.Core.Runtime /// protected IProfilingLogger ProfilingLogger { get; private set; } + /// + public IRuntimeState State => _state; + /// public virtual void Boot(IContainer container) { // assign current container - Current.Container = container; + Current.Container = _container = container; // create and register the essential services // ie the bare minimum required to boot @@ -74,8 +76,9 @@ namespace Umbraco.Core.Runtime container.RegisterInstance(runtimeCache); // database factory - var databaseFactory = new UmbracoDatabaseFactory(logger, new Lazy(container.GetInstance)); - container.RegisterSingleton(factory => factory.GetInstance().SqlContext); + var databaseFactory = GetDatabaseFactory(); + container.RegisterInstance(databaseFactory); + container.RegisterSingleton(factory => databaseFactory.SqlContext); // type loader var globalSettings = UmbracoConfig.For.GlobalSettings(); @@ -92,6 +95,7 @@ namespace Umbraco.Core.Runtime }; container.RegisterInstance(_state); + // register runtime-level services Compose(composition); // the boot loader boots using a container scope, so anything that is PerScope will @@ -125,14 +129,10 @@ namespace Umbraco.Core.Runtime _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 + // fixme split Container into Register and Factory + // we should have a Current.Factory not a Current.Container + // we should compile the register into a factory *now* + // using the factory before this point should just throw _components.Initialize(); } @@ -264,23 +264,7 @@ namespace Umbraco.Core.Runtime /// 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 - // FIXME should be essentially empty! move all to component! - - container.ComposeConfiguration(); - - // 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 - composition.GetCollectionBuilder().AddCoreMappers(); - - // register the scope provider - container.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor - container.RegisterSingleton(f => f.GetInstance()); - container.RegisterSingleton(f => f.GetInstance()); + // nothing } private RuntimeLevel DetermineRuntimeLevel2(IUmbracoDatabaseFactory databaseFactory) @@ -431,6 +415,13 @@ namespace Umbraco.Core.Runtime protected virtual string GetApplicationRootPath() => null; + /// + /// Gets the database factory. + /// + /// This is strictly internal, for tests only. + protected internal virtual IUmbracoDatabaseFactory GetDatabaseFactory() + => new UmbracoDatabaseFactory(Logger, new Lazy(_container.GetInstance)); + #endregion } } diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 058c2ed593..7fbdd46f36 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Migrations; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.Scoping; @@ -33,11 +34,25 @@ namespace Umbraco.Core.Runtime { base.Compose(composition); + var container = composition.Container; + // composers - composition.Container.ComposeRepositories(); - composition.Container.ComposeServices(); - composition.Container.ComposeCoreMappingProfiles(); - composition.Container.ComposeFileSystems(); + composition + .ComposeConfiguration() + .ComposeRepositories() + .ComposeServices() + .ComposeCoreMappingProfiles() + .ComposeFileSystems(); + + // 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 + 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 database builder // *not* a singleton, don't want to keep it around @@ -79,7 +94,7 @@ namespace Umbraco.Core.Runtime factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), - factory.GetInstance(), + factory.GetInstance(), factory.GetInstance(), true, new DatabaseServerMessengerOptions())); diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs index 20f9276ba1..5cfcb501e5 100644 --- a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs @@ -33,7 +33,7 @@ namespace Umbraco.Core.Sync private readonly IRuntimeState _runtime; private readonly ManualResetEvent _syncIdle; private readonly object _locko = new object(); - private readonly ProfilingLogger _profilingLogger; + private readonly IProfilingLogger _profilingLogger; private readonly ISqlContext _sqlContext; private readonly Lazy _distCacheFilePath; private int _lastId = -1; @@ -46,7 +46,7 @@ namespace Umbraco.Core.Sync public DatabaseServerMessengerOptions Options { get; } public DatabaseServerMessenger( - IRuntimeState runtime, IScopeProvider scopeProvider, ISqlContext sqlContext, ProfilingLogger proflog, IGlobalSettings globalSettings, + IRuntimeState runtime, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IGlobalSettings globalSettings, bool distributedEnabled, DatabaseServerMessengerOptions options) : base(distributedEnabled) { @@ -54,7 +54,7 @@ namespace Umbraco.Core.Sync _sqlContext = sqlContext; _runtime = runtime; _profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog)); - Logger = proflog.Logger; + Logger = proflog; Options = options ?? throw new ArgumentNullException(nameof(options)); _lastPruned = _lastSync = DateTime.UtcNow; _syncIdle = new ManualResetEvent(true); diff --git a/src/Umbraco.Examine/UmbracoContentIndexer.cs b/src/Umbraco.Examine/UmbracoContentIndexer.cs index fab9f226a4..33590d12db 100644 --- a/src/Umbraco.Examine/UmbracoContentIndexer.cs +++ b/src/Umbraco.Examine/UmbracoContentIndexer.cs @@ -75,7 +75,7 @@ namespace Umbraco.Examine IEnumerable fieldDefinitions, Directory luceneDirectory, Analyzer defaultAnalyzer, - ProfilingLogger profilingLogger, + IProfilingLogger profilingLogger, IContentService contentService, IMediaService mediaService, IUserService userService, @@ -212,7 +212,7 @@ namespace Umbraco.Examine var filtered = c.RawQuery(rawQuery); var results = searcher.Search(filtered); - ProfilingLogger.Logger.Debug(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, results.TotalItemCount); + ProfilingLogger.Debug(GetType(), "DeleteFromIndex with query: {Query} (found {TotalItems} results)", rawQuery, results.TotalItemCount); //need to queue a delete item for each one found foreach (var r in results) diff --git a/src/Umbraco.Examine/UmbracoExamineIndexer.cs b/src/Umbraco.Examine/UmbracoExamineIndexer.cs index a4c1fb4336..3f30a02f28 100644 --- a/src/Umbraco.Examine/UmbracoExamineIndexer.cs +++ b/src/Umbraco.Examine/UmbracoExamineIndexer.cs @@ -76,7 +76,7 @@ namespace Umbraco.Examine IEnumerable fieldDefinitions, Directory luceneDirectory, Analyzer defaultAnalyzer, - ProfilingLogger profilingLogger, + IProfilingLogger profilingLogger, IValueSetValidator validator = null, IReadOnlyDictionary> indexValueTypes = null) : base(name, fieldDefinitions, luceneDirectory, defaultAnalyzer, validator, indexValueTypes) @@ -114,7 +114,7 @@ namespace Umbraco.Examine new FieldDefinition(IconFieldName, FieldDefinitionTypes.Raw) }; - protected ProfilingLogger ProfilingLogger { get; } + protected IProfilingLogger ProfilingLogger { get; } /// /// Overridden to ensure that the umbraco system field definitions are in place @@ -162,7 +162,7 @@ namespace Umbraco.Examine /// public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) { - ProfilingLogger.Logger.Debug(GetType(), "{IndexerName} indexer initializing", name); + ProfilingLogger.Debug(GetType(), "{IndexerName} indexer initializing", name); if (config["enableDefaultEventHandler"] != null && bool.TryParse(config["enableDefaultEventHandler"], out var enabled)) { @@ -253,7 +253,7 @@ namespace Umbraco.Examine { if (CanInitialize()) { - ProfilingLogger.Logger.Debug(GetType(), "Rebuilding index"); + ProfilingLogger.Debug(GetType(), "Rebuilding index"); using (new SafeCallContext()) { base.RebuildIndex(); @@ -334,7 +334,7 @@ namespace Umbraco.Examine /// protected override void OnIndexingError(IndexingErrorEventArgs ex) { - ProfilingLogger.Logger.Error(GetType(), ex.InnerException, ex.Message); + ProfilingLogger.Error(GetType(), ex.InnerException, ex.Message); base.OnIndexingError(ex); } @@ -359,7 +359,7 @@ namespace Umbraco.Examine } } - ProfilingLogger.Logger.Debug(GetType(), + ProfilingLogger.Debug(GetType(), "Write lucene doc id:{DocumentId}, category:{DocumentCategory}, type:{DocumentItemType}", docArgs.ValueSet.Id, docArgs.ValueSet.Category, @@ -374,7 +374,7 @@ namespace Umbraco.Examine /// protected override void AddDocument(Document doc, IndexItem item, IndexWriter writer) { - ProfilingLogger.Logger.Debug(GetType(), + ProfilingLogger.Debug(GetType(), "AddDocument {DocumentId} with type {DocumentItemType}", item.ValueSet.Id, item.ValueSet.ItemType); diff --git a/src/Umbraco.Examine/UmbracoMemberIndexer.cs b/src/Umbraco.Examine/UmbracoMemberIndexer.cs index 82bf3b9cf6..ea060693d5 100644 --- a/src/Umbraco.Examine/UmbracoMemberIndexer.cs +++ b/src/Umbraco.Examine/UmbracoMemberIndexer.cs @@ -49,7 +49,7 @@ namespace Umbraco.Examine IEnumerable fieldDefinitions, Directory luceneDirectory, Analyzer analyzer, - ProfilingLogger profilingLogger, + IProfilingLogger profilingLogger, IValueSetValidator validator, IMemberService memberService) : base(name, fieldDefinitions, luceneDirectory, analyzer, profilingLogger, validator) diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index 4842b3feec..c72f7949f5 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -4,6 +4,7 @@ using System.Text; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Composing; using Umbraco.Core.Composing.Composers; @@ -28,13 +29,14 @@ namespace Umbraco.Tests.IO SettingsForTests.ConfigureSettings(config); _container = Current.Container = ContainerFactory.Create(); + var composition = new Composition(_container, RuntimeLevel.Run); _container.Register(_ => Mock.Of()); _container.Register(_ => Mock.Of()); _container.Register(_ => Mock.Of()); _container.RegisterSingleton(); - _container.ComposeFileSystems(); + composition.ComposeFileSystems(); // make sure we start clean // because some tests will create corrupt or weird filesystems diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 6353224b2a..aed31ca1be 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -42,7 +42,7 @@ namespace Umbraco.Tests.Models base.Compose(); Container.Register(_ => Mock.Of()); - Container.ComposeFileSystems(); + Composition.ComposeFileSystems(); Container.Register(_ => Mock.Of()); Container.Register(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 907de9ccde..f92b4264ec 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Data; using System.Web.Hosting; using Examine; using Moq; @@ -7,9 +8,12 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Events; +using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; +using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; @@ -17,13 +21,18 @@ using Umbraco.Web; namespace Umbraco.Tests.Runtimes { [TestFixture] - [Ignore("cannot work until we refactor IUmbracoDatabaseFactory vs UmbracoDatabaseFactory")] public class CoreRuntimeTests { [SetUp] public void SetUp() { TestComponent.Reset(); + + // cannot boot runtime without some configuration + var umbracoSettings = SettingsForTests.GenerateMockUmbracoSettings(); + var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); + SettingsForTests.ConfigureSettings(umbracoSettings); + SettingsForTests.ConfigureSettings(globalSettings); } public void TearDown() @@ -38,12 +47,29 @@ namespace Umbraco.Tests.Runtimes { app.HandleApplicationStart(app, new EventArgs()); + var e = app.Runtime.State.BootFailedException; + var m = ""; + switch (e) + { + case null: + m = ""; + break; + case BootFailedException bfe when bfe.InnerException != null: + m = "BootFailed: " + bfe.InnerException.GetType() + " " + bfe.InnerException.Message + " " + bfe.InnerException.StackTrace; + break; + default: + m = e.GetType() + " " + e.Message + " " + e.StackTrace; + break; + } + + Assert.AreNotEqual(RuntimeLevel.BootFailed, app.Runtime.State.Level, m); Assert.IsTrue(TestComponent.Ctored); Assert.IsTrue(TestComponent.Composed); Assert.IsTrue(TestComponent.Initialized1); Assert.IsTrue(TestComponent.Initialized2); Assert.IsNotNull(TestComponent.ProfilingLogger); - Assert.IsInstanceOf(TestComponent.ProfilingLogger.Logger); + Assert.IsInstanceOf(TestComponent.ProfilingLogger); + Assert.IsInstanceOf(((ProfilingLogger) TestComponent.ProfilingLogger).Logger); // note: components are NOT disposed after boot @@ -57,42 +83,23 @@ namespace Umbraco.Tests.Runtimes // test application public class TestUmbracoApplication : UmbracoApplicationBase { + public IRuntime Runtime { get; private set; } + protected override IRuntime GetRuntime() { - return new TestRuntime(); + return Runtime = new TestRuntime(); } } // test runtime public class TestRuntime : CoreRuntime { - // the application's logger is created by the application - // through GetLogger, that custom application can override - protected override ILogger GetLogger() - { - //return Mock.Of(); - return new DebugDiagnosticsLogger(); - } - - public override void Compose(Composition composition) - { - base.Compose(composition); - - var container = composition.Container; - - // the application's profiler and profiling logger are - // registered by CoreRuntime.Compose() but can be - // overriden afterwards - they haven't been resolved yet - container.RegisterSingleton(_ => new TestProfiler()); - container.RegisterSingleton(factory => new ProfilingLogger(factory.GetInstance(), factory.GetInstance())); - - // must override the database factory - container.RegisterSingleton(_ => GetDatabaseFactory()); - } + protected override ILogger GetLogger() => new DebugDiagnosticsLogger(); + protected override IProfiler GetProfiler() => new TestProfiler(); // must override the database factory // else BootFailedException because U cannot connect to the configured db - private static IUmbracoDatabaseFactory GetDatabaseFactory() + protected internal override IUmbracoDatabaseFactory GetDatabaseFactory() { var mock = new Mock(); mock.Setup(x => x.Configured).Returns(true); @@ -107,6 +114,26 @@ namespace Umbraco.Tests.Runtimes return true; } + // because we don't even have the core runtime component, + // there are a few required stuff that we need to compose + public override void Compose(Composition composition) + { + base.Compose(composition); + + var scopeProvider = Mock.Of(); + Mock.Get(scopeProvider) + .Setup(x => x.CreateScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(Mock.Of()); + + composition.Container.RegisterInstance(scopeProvider); + } + private MainDom _mainDom; public override void Boot(IContainer container) @@ -139,7 +166,7 @@ namespace Umbraco.Tests.Runtimes public static bool Initialized1; public static bool Initialized2; public static bool Terminated; - public static ProfilingLogger ProfilingLogger; + public static IProfilingLogger ProfilingLogger; public static void Reset() { @@ -172,7 +199,7 @@ namespace Umbraco.Tests.Runtimes Initialized2 = true; } - public void Initialize(ProfilingLogger proflog) + public void Initialize(IProfilingLogger proflog) { ProfilingLogger = proflog; } diff --git a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs index 680eddf953..aa41bdd613 100644 --- a/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeFileSystemsTests.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Scoping if (!withApplication) return; // re-register with actual media fs - Container.ComposeFileSystems(); + Composition.ComposeFileSystems(); } public override void TearDown() diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index 05793e85dd..49b52f4276 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -61,7 +61,7 @@ namespace Umbraco.Tests.Services.Importing if (!withApplication) return; // re-register with actual media fs - Container.ComposeFileSystems(); + Composition.ComposeFileSystems(); } [Test] diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index ee5768d499..969bfff4fe 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -225,8 +225,9 @@ namespace Umbraco.Tests.Testing { if (configure == false) return; - Container.ComposeCoreMappingProfiles(); - Container.ComposeWebMappingProfiles(); + Composition + .ComposeCoreMappingProfiles() + .ComposeWebMappingProfiles(); } protected virtual void ComposePluginManager(UmbracoTestOptions.PluginManager pluginManager) @@ -285,7 +286,7 @@ namespace Umbraco.Tests.Testing SettingsForTests.ConfigureSettings(globalSettings); // default Datalayer/Repositories/SQL/Database/etc... - Container.ComposeRepositories(); + Composition.ComposeRepositories(); // register basic stuff that might need to be there for some container resolvers to work Container.RegisterSingleton(factory => umbracoSettings); @@ -326,7 +327,7 @@ namespace Umbraco.Tests.Testing => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); Container.RegisterSingleton(factory => (IScopeAccessor) factory.GetInstance()); - Container.ComposeServices(); + Composition.ComposeServices(); // composition root is doing weird things, fix Container.RegisterSingleton(); diff --git a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs index 889ef195a5..2225c369df 100644 --- a/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs @@ -1,6 +1,7 @@ using System.Reflection; using System.Web.Http.Controllers; using System.Web.Mvc; +using Umbraco.Core.Components; using Umbraco.Core.Composing; namespace Umbraco.Web.Composing.Composers @@ -10,27 +11,31 @@ namespace Umbraco.Web.Composing.Composers /// /// Registers all IControllers using the TypeLoader for scanning and caching found instances for the calling assembly /// - public static IContainer ComposeMvcControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) + public static Composition ComposeMvcControllers(this Composition composition, TypeLoader typeLoader, Assembly assembly) { + var container = composition.Container; + //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. container.RegisterControllers(typeLoader, assembly); - return container; + return composition; } /// /// Registers all IHttpController using the TypeLoader for scanning and caching found instances for the calling assembly /// - public static IContainer ComposeApiControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) + public static Composition ComposeApiControllers(this Composition composition, TypeLoader typeLoader, Assembly assembly) { + var container = composition.Container; + //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. container.RegisterControllers(typeLoader, assembly); - return container; + return composition; } private static void RegisterControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) diff --git a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs index b9acc636c5..3d1a5b5c43 100644 --- a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Composing; +using Umbraco.Core.Components; +using Umbraco.Core.Composing; using Umbraco.Web.Install; using Umbraco.Web.Install.InstallSteps; @@ -6,8 +7,10 @@ namespace Umbraco.Web.Composing.Composers { public static class InstallerComposer { - public static IContainer ComposeInstaller(this IContainer container) + public static Composition ComposeInstaller(this Composition composition) { + var container = composition.Container; + // register the installer steps container.Register(Lifetime.Scope); @@ -28,7 +31,7 @@ namespace Umbraco.Web.Composing.Composers container.Register(); container.Register(); - return container; + return composition; } } } diff --git a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs index c5629b983e..4779ba129b 100644 --- a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs @@ -1,5 +1,6 @@ using AutoMapper; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Web.Models.ContentEditing; @@ -10,8 +11,10 @@ namespace Umbraco.Web.Composing.Composers { public static class WebMappingProfilesComposer { - public static IContainer ComposeWebMappingProfiles(this IContainer container) + public static Composition ComposeWebMappingProfiles(this Composition composition) { + var container = composition.Container; + //register the profiles container.Register(); container.Register(); @@ -44,7 +47,7 @@ namespace Umbraco.Web.Composing.Composers container.Register(); container.Register(); - return container; + return composition; } } } diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 9fc7a8a941..d0d6aeb2fa 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -120,7 +120,7 @@ namespace Umbraco.Web.Composing internal static EditorValidatorCollection EditorValidators => Container.GetInstance(); - + internal static UmbracoApiControllerTypeCollection UmbracoApiControllerTypes => Container.GetInstance(); @@ -230,7 +230,7 @@ namespace Umbraco.Web.Composing public static IProfiler Profiler => CoreCurrent.Profiler; - public static ProfilingLogger ProfilingLogger => CoreCurrent.ProfilingLogger; + public static IProfilingLogger ProfilingLogger => CoreCurrent.ProfilingLogger; public static CacheHelper ApplicationCache => CoreCurrent.ApplicationCache; diff --git a/src/Umbraco.Web/Macros/MacroRenderer.cs b/src/Umbraco.Web/Macros/MacroRenderer.cs index a8c89f179a..5ba9de6577 100755 --- a/src/Umbraco.Web/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web/Macros/MacroRenderer.cs @@ -27,11 +27,11 @@ namespace Umbraco.Web.Macros { public class MacroRenderer { - private readonly ProfilingLogger _plogger; + private readonly IProfilingLogger _plogger; // todo: there are many more things that would need to be injected in here - public MacroRenderer(ProfilingLogger plogger) + public MacroRenderer(IProfilingLogger plogger) { _plogger = plogger; } @@ -143,7 +143,7 @@ namespace Umbraco.Web.Macros var key = member?.ProviderUserKey; if (key == null) return; } - + // this is legacy and I'm not sure what exactly it is supposed to do if (macroContent.Control != null) macroContent.ControlId = macroContent.Control.ID; @@ -304,7 +304,7 @@ namespace Umbraco.Web.Macros { Exceptions.Add(e); - _plogger.Logger.Warn(e, "Failed {MsgIn}", msgIn); + _plogger.Warn(e, "Failed {MsgIn}", msgIn); var macroErrorEventArgs = new MacroErrorEventArgs { @@ -362,7 +362,7 @@ namespace Umbraco.Web.Macros "Executed PartialView.", () => ExecutePartialView(model), () => textService.Localize("errors/macroErrorLoadingPartialView", new[] { model.MacroSource })); - + case MacroTypes.UserControl: return ExecuteMacroWithErrorWrapper(model, $"Loading UserControl: MacroSource=\"{model.MacroSource}\".", diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 52bf980853..3e4d2c1c1f 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -23,7 +23,6 @@ namespace Umbraco.Web.Runtime /// /// public WebRuntime(UmbracoApplicationBase umbracoApplication) - : base() { _umbracoApplication = umbracoApplication; } diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 3705eea086..c3c74f0c0b 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -70,12 +70,12 @@ namespace Umbraco.Web.Runtime container.RegisterSingleton(); // required for hybrid accessors - container.ComposeWebMappingProfiles(); + composition.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 - container.ComposeInstaller(); + composition.ComposeInstaller(); // register membership stuff container.Register(factory => Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider()); @@ -125,8 +125,9 @@ namespace Umbraco.Web.Runtime // configure the container for web container.ConfigureForWeb(); - container.ComposeMvcControllers(typeLoader, GetType().Assembly); - container.ComposeApiControllers(typeLoader, GetType().Assembly); + composition + .ComposeMvcControllers(typeLoader, GetType().Assembly) + .ComposeApiControllers(typeLoader, GetType().Assembly); composition.GetCollectionBuilder() .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?! diff --git a/src/Umbraco.Web/Suspendable.cs b/src/Umbraco.Web/Suspendable.cs index beb0029f4f..e7c0c34d80 100644 --- a/src/Umbraco.Web/Suspendable.cs +++ b/src/Umbraco.Web/Suspendable.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web public static void SuspendDocumentCache() { - Current.ProfilingLogger.Logger.Info(typeof (PageCacheRefresher), "Suspend document cache."); + Current.Logger.Info(typeof (PageCacheRefresher), "Suspend document cache."); _suspended = true; } @@ -39,7 +39,7 @@ namespace Umbraco.Web { _suspended = false; - Current.ProfilingLogger.Logger.Info(typeof (PageCacheRefresher), "Resume document cache (reload:{Tried}).", _tried); + Current.Logger.Info(typeof (PageCacheRefresher), "Resume document cache (reload:{Tried}).", _tried); if (_tried == false) return; _tried = false; @@ -65,7 +65,7 @@ namespace Umbraco.Web public static void SuspendIndexers() { - Current.ProfilingLogger.Logger.Info(typeof (ExamineEvents), "Suspend indexers."); + Current.Logger.Info(typeof (ExamineEvents), "Suspend indexers."); _suspended = true; } @@ -73,7 +73,7 @@ namespace Umbraco.Web { _suspended = false; - Current.ProfilingLogger.Logger.Info(typeof (ExamineEvents), "Resume indexers (rebuild:{Tried}).", _tried); + Current.Logger.Info(typeof (ExamineEvents), "Resume indexers (rebuild:{Tried}).", _tried); if (_tried == false) return; _tried = false; @@ -93,13 +93,13 @@ namespace Umbraco.Web public static void Suspend() { - Current.ProfilingLogger.Logger.Info(typeof (ScheduledPublishing), "Suspend scheduled publishing."); + Current.Logger.Info(typeof (ScheduledPublishing), "Suspend scheduled publishing."); _suspended = true; } public static void Resume() { - Current.ProfilingLogger.Logger.Info(typeof (ScheduledPublishing), "Resume scheduled publishing."); + Current.Logger.Info(typeof (ScheduledPublishing), "Resume scheduled publishing."); _suspended = false; } } diff --git a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs index 744b77ac50..d9dae18b14 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoControl.cs @@ -3,7 +3,6 @@ using System.Web.Mvc; using System.Web.UI; using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Composing; @@ -47,7 +46,7 @@ namespace Umbraco.Web.UI.Controls /// /// Gets the profiling logger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets the Umbraco context. diff --git a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs index 62e94ddded..e1c81d9a35 100644 --- a/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs +++ b/src/Umbraco.Web/UI/Controls/UmbracoUserControl.cs @@ -1,12 +1,8 @@ using System; -using System.Web; using System.Web.Mvc; -using System.Web.Routing; using System.Web.UI; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Security; @@ -75,7 +71,7 @@ namespace Umbraco.Web.UI.Controls /// /// Gets the ProfilingLogger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets the Umbraco context. diff --git a/src/Umbraco.Web/UI/Pages/BasePage.cs b/src/Umbraco.Web/UI/Pages/BasePage.cs index def4288c6d..5974dfcbe8 100644 --- a/src/Umbraco.Web/UI/Pages/BasePage.cs +++ b/src/Umbraco.Web/UI/Pages/BasePage.cs @@ -1,14 +1,11 @@ using System; using System.Web; using System.Web.Mvc; -using System.Web.Routing; -using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Web.Security; using System.Web.UI; -using Umbraco.Core.Persistence; using Umbraco.Web.Composing; namespace Umbraco.Web.UI.Pages @@ -33,7 +30,7 @@ namespace Umbraco.Web.UI.Pages /// /// Gets the profiling helper. /// - public ProfilingLogger ProfilingLogger => Current.ProfilingLogger; + public IProfilingLogger ProfilingLogger => Current.ProfilingLogger; /// /// Gets the Url helper. diff --git a/src/Umbraco.Web/UmbracoHttpHandler.cs b/src/Umbraco.Web/UmbracoHttpHandler.cs index e64c4c5fe1..c1cf460c81 100644 --- a/src/Umbraco.Web/UmbracoHttpHandler.cs +++ b/src/Umbraco.Web/UmbracoHttpHandler.cs @@ -1,11 +1,8 @@ using System; using System.Web; using System.Web.Mvc; -using System.Web.Routing; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Security; @@ -44,7 +41,7 @@ namespace Umbraco.Web /// /// Gets the ProfilingLogger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets the Umbraco context. diff --git a/src/Umbraco.Web/UmbracoWebService.cs b/src/Umbraco.Web/UmbracoWebService.cs index 20db7208b5..fbe4eb9f04 100644 --- a/src/Umbraco.Web/UmbracoWebService.cs +++ b/src/Umbraco.Web/UmbracoWebService.cs @@ -40,7 +40,7 @@ namespace Umbraco.Web /// /// Gets the ProfilingLogger. /// - public ProfilingLogger ProfilingLogger { get; } + public IProfilingLogger ProfilingLogger { get; } /// /// Gets the Umbraco context.