From c6891c6c7000f4e0bcda5d954379aff512d30ef5 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 29 Nov 2018 10:35:16 +0100 Subject: [PATCH] RegisterUnique --- src/Umbraco.Core/Components/Composition.cs | 85 +++++++- .../Components/CompositionExtensions.cs | 72 +++++-- .../Composers/FileSystemsComposer.cs | 6 +- .../Composers/RepositoriesComposer.cs | 70 +++--- .../Composing/Composers/ServicesComposer.cs | 62 +++--- .../Composing/CompositionExtensions.cs | 32 +++ src/Umbraco.Core/Composing/IFactory.cs | 8 + src/Umbraco.Core/Composing/IRegister.cs | 8 - src/Umbraco.Core/Composing/Lifetime.cs | 21 ++ .../LightInject/LightInjectContainer.cs | 12 +- .../LightInject}/LightInjectException.cs | 4 +- .../LightInject/LightInjectExtensions.cs | 199 ------------------ .../Composing/RegisterExtensions.cs | 62 +----- src/Umbraco.Core/IRuntime.cs | 3 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 27 +-- .../Runtime/CoreRuntimeComponent.cs | 24 +-- src/Umbraco.Core/Umbraco.Core.csproj | 4 +- .../DistributedCache/DistributedCacheTests.cs | 6 +- ...ngTests.cs => ContainerConformingTests.cs} | 57 ++++- .../Composing/PackageActionCollectionTests.cs | 2 +- .../CoreThings/TryConvertToTests.cs | 3 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 4 +- .../Integration/ContentEventsTests.cs | 2 +- .../Models/Mapping/AutoMapperTests.cs | 4 +- .../Mapping/ContentTypeModelMappingTests.cs | 14 +- .../Mapping/ContentWebModelMappingTests.cs | 5 +- .../PartialViewRepositoryTests.cs | 4 +- .../Repositories/ScriptRepositoryTest.cs | 4 +- .../PropertyEditors/ImageCropperTest.cs | 2 +- .../PropertyEditorValueEditorTests.cs | 5 +- .../Published/ConvertersTests.cs | 2 +- .../PublishedContentLanguageVariantTests.cs | 5 +- .../PublishedContentSnapshotTestBase.cs | 4 +- .../PublishedContent/PublishedContentTests.cs | 8 +- .../Routing/RenderRouteHandlerTests.cs | 19 +- .../Routing/UrlRoutingTestBase.cs | 2 +- .../Routing/UrlsProviderWithDomainsTests.cs | 2 +- .../Routing/UrlsWithNestedDomains.cs | 2 +- .../Runtimes/CoreRuntimeTests.cs | 11 +- .../Scoping/ScopeEventDispatcherTests.cs | 4 +- .../Scoping/ScopedNuCacheTests.cs | 4 +- .../Scoping/ScopedRepositoryTests.cs | 4 +- src/Umbraco.Tests/Scoping/ScopedXmlTests.cs | 4 +- .../Services/ContentServiceTests.cs | 12 +- .../ContentTypeServiceVariantsTests.cs | 5 +- .../Strings/DefaultShortStringHelperTests.cs | 2 +- .../Strings/StringExtensionsTests.cs | 12 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 10 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 4 +- .../TestHelpers/TestWithDatabaseBase.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 69 +++--- .../TreesAndSections/SectionTests.cs | 4 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 2 +- .../UmbracoExamine/ExamineBaseTest.cs | 2 +- .../Web/Controllers/ContentControllerTests.cs | 16 +- .../Web/Controllers/UsersControllerTests.cs | 6 +- .../Components/NotificationsComponent.cs | 2 +- .../LightInject/LightInjectContainer.cs | 2 +- src/Umbraco.Web/CompositionExtensions.cs | 21 +- src/Umbraco.Web/Runtime/WebRuntime.cs | 15 +- .../Runtime/WebRuntimeComponent.cs | 43 ++-- .../SignalR/PreviewHubComponent.cs | 3 +- src/Umbraco.Web/UmbracoApplicationBase.cs | 8 +- 63 files changed, 520 insertions(+), 602 deletions(-) create mode 100644 src/Umbraco.Core/Composing/CompositionExtensions.cs rename src/Umbraco.Core/{Exceptions => Composing/LightInject}/LightInjectException.cs (96%) delete mode 100644 src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs rename src/Umbraco.Tests/Composing/{ContainerConfirmingTests.cs => ContainerConformingTests.cs} (80%) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 525d8b773e..2f5bd0f6ee 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -16,6 +16,7 @@ namespace Umbraco.Core.Components public class Composition : IRegister { private readonly Dictionary _builders = new Dictionary(); + private readonly Dictionary _uniques = new Dictionary(); private readonly IRegister _register; /// @@ -81,13 +82,87 @@ namespace Umbraco.Core.Components public void ConfigureForWeb() => _register.ConfigureForWeb(); - /// - public void EnablePerWebRequestScope() - => _register.EnablePerWebRequestScope(); - /// public IFactory CreateFactory() - => _register.CreateFactory(); + { + foreach (var unique in _uniques.Values) + unique.RegisterTo(_register); + + return _register.CreateFactory(); + } + + #endregion + + #region Unique + + /// + /// Registers a unique service. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Type serviceType, Type implementingType) + => _uniques[serviceType] = new Unique(serviceType, implementingType); + + /// + /// Registers a unique service. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Type serviceType, object instance) + => _uniques[serviceType] = new Unique(serviceType, instance); + + /// + /// Registers a unique service. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Func factory) + => _uniques[typeof(TService)] = new Unique(factory); + + private class Unique + { + private readonly Type _serviceType; + private readonly Type _implementingType; + private readonly object _instance; + + protected Unique(Type serviceType) + { + _serviceType = serviceType; + } + + public Unique(Type serviceType, Type implementingType) + : this(serviceType) + { + _implementingType = implementingType; + } + + public Unique(Type serviceType, object instance) + : this(serviceType) + { + _instance = instance; + } + + public virtual void RegisterTo(IRegister register) + { + if (_implementingType != null) + register.Register(_serviceType, _implementingType, Lifetime.Singleton); + else if (_instance != null) + register.RegisterInstance(_serviceType, _instance); + } + } + + private class Unique : Unique + { + private readonly Func _factory; + + public Unique(Func factory) + : base(typeof(TService)) + { + _factory = factory; + } + + public override void RegisterTo(IRegister register) + { + register.Register(_factory, Lifetime.Singleton); + } + } #endregion diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index f41ecf7186..fa98038455 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -2,6 +2,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Dictionary; using Umbraco.Core.Composing; +using Umbraco.Core.IO; using Umbraco.Core.Migrations; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Mappers; @@ -17,6 +18,45 @@ namespace Umbraco.Core.Components /// public static class CompositionExtensions { + #region FileSystems + + /// + /// Registers a filesystem. + /// + /// The type of the filesystem. + /// The implementing type. + /// The composition. + /// A factory method creating the supporting filesystem. + /// The register. + public static void RegisterFileSystem(this Composition composition, Func supportingFileSystemFactory) + where TImplementing : FileSystemWrapper, TFileSystem + { + composition.RegisterUnique(factory => + { + var fileSystems = factory.GetInstance(); + return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); + }); + } + + /// + /// Registers a filesystem. + /// + /// The type of the filesystem. + /// The composition. + /// A factory method creating the supporting filesystem. + /// The register. + public static void RegisterFileSystem(this Composition composition, Func supportingFileSystemFactory) + where TFileSystem : FileSystemWrapper + { + composition.RegisterUnique(factory => + { + var fileSystems = factory.GetInstance(); + return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); + }); + } + + #endregion + #region Collection Builders /// @@ -77,7 +117,7 @@ namespace Umbraco.Core.Components #endregion - #region Singleton + #region Uniques /// /// Sets the culture dictionary factory. @@ -87,7 +127,7 @@ namespace Umbraco.Core.Components public static void SetCultureDictionaryFactory(this Composition composition) where T : ICultureDictionaryFactory { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -97,7 +137,7 @@ namespace Umbraco.Core.Components /// A function creating a culture dictionary factory. public static void SetCultureDictionaryFactory(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -107,7 +147,7 @@ namespace Umbraco.Core.Components /// A factory. public static void SetCultureDictionaryFactory(this Composition composition, ICultureDictionaryFactory factory) { - composition.RegisterSingleton(_ => factory); + composition.RegisterUnique(_ => factory); } /// @@ -118,7 +158,7 @@ namespace Umbraco.Core.Components public static void SetPublishedContentModelFactory(this Composition composition) where T : IPublishedModelFactory { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -128,7 +168,7 @@ namespace Umbraco.Core.Components /// A function creating a published content model factory. public static void SetPublishedContentModelFactory(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -138,7 +178,7 @@ namespace Umbraco.Core.Components /// A published content model factory. public static void SetPublishedContentModelFactory(this Composition composition, IPublishedModelFactory factory) { - composition.RegisterSingleton(_ => factory); + composition.RegisterUnique(_ => factory); } /// @@ -149,7 +189,7 @@ namespace Umbraco.Core.Components public static void SetServerRegistrar(this Composition composition) where T : IServerRegistrar { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -159,7 +199,7 @@ namespace Umbraco.Core.Components /// A function creating a server registar. public static void SetServerRegistrar(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -169,7 +209,7 @@ namespace Umbraco.Core.Components /// A server registrar. public static void SetServerRegistrar(this Composition composition, IServerRegistrar registrar) { - composition.RegisterSingleton(_ => registrar); + composition.RegisterUnique(_ => registrar); } /// @@ -180,7 +220,7 @@ namespace Umbraco.Core.Components public static void SetServerMessenger(this Composition composition) where T : IServerMessenger { - composition.Register(Lifetime.Singleton); + composition.RegisterUnique(); } /// @@ -190,7 +230,7 @@ namespace Umbraco.Core.Components /// A function creating a server messenger. public static void SetServerMessenger(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -200,7 +240,7 @@ namespace Umbraco.Core.Components /// A server messenger. public static void SetServerMessenger(this Composition composition, IServerMessenger registrar) { - composition.RegisterSingleton(_ => registrar); + composition.RegisterUnique(_ => registrar); } /// @@ -211,7 +251,7 @@ namespace Umbraco.Core.Components public static void SetShortStringHelper(this Composition composition) where T : IShortStringHelper { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -221,7 +261,7 @@ namespace Umbraco.Core.Components /// A function creating a short string helper. public static void SetShortStringHelper(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -231,7 +271,7 @@ namespace Umbraco.Core.Components /// A short string helper. public static void SetShortStringHelper(this Composition composition, IShortStringHelper helper) { - composition.RegisterSingleton(_ => helper); + composition.RegisterUnique(_ => helper); } #endregion diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index 1970fc7f4c..f1fb095406 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -71,13 +71,13 @@ namespace Umbraco.Core.Composing.Composers // 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 // interface is really for end-users to get access to filesystems. - composition.RegisterSingleton(factory => factory.CreateInstance(factory)); + composition.RegisterUnique(factory => factory.CreateInstance(factory)); // register IFileSystems, which gives access too all filesystems - composition.RegisterSingleton(factory => factory.GetInstance()); + composition.RegisterUnique(factory => factory.GetInstance()); // register the scheme for media paths - composition.RegisterSingleton(); + composition.RegisterUnique(); // register the IMediaFileSystem implementation with a supporting filesystem composition.RegisterFileSystem( diff --git a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs index 54f9ff3e53..62b92081c1 100644 --- a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs @@ -12,41 +12,41 @@ namespace Umbraco.Core.Composing.Composers public static Composition ComposeRepositories(this Composition composition) { // repositories - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); return composition; } diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index ec53f7efdc..1b77aaa7d6 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -17,49 +17,49 @@ namespace Umbraco.Core.Composing.Composers { // register a transient messages factory, which will be replaced by the web // boot manager when running in a web context - composition.RegisterSingleton(); + composition.RegisterUnique(); // register the service context - composition.RegisterSingleton(); + composition.RegisterUnique(); // register the special idk map - composition.RegisterSingleton(); + composition.RegisterUnique(); // register the services - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); composition.Register(SourcesFactory); - composition.RegisterSingleton(factory => new LocalizedTextService( + composition.RegisterUnique(factory => new LocalizedTextService( factory.GetInstance>(), factory.GetInstance())); //TODO: These are replaced in the web project - we need to declare them so that // something is wired up, just not sure this is very nice but will work for now. - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); return composition; } diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs new file mode 100644 index 0000000000..bab3bb7fa5 --- /dev/null +++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs @@ -0,0 +1,32 @@ +using Umbraco.Core.Components; + +namespace Umbraco.Core.Composing +{ + /// + /// Provides extension methods to the class. + /// + public static class CompositionExtensions + { + #region Unique + + /// + /// Registers a unique service as its own implementation. + /// + public static void RegisterUnique(this Composition composition) + => composition.RegisterUnique(typeof(TService), typeof(TService)); + + /// + /// Registers a unique service with an implementation type. + /// + public static void RegisterUnique(this Composition composition) + => composition.RegisterUnique(typeof(TService), typeof(TImplementing)); + + /// + /// Registers a unique service with an implementing instance. + /// + public static void RegisterUnique(this Composition composition, TService instance) + => composition.RegisterUnique(typeof(TService), instance); + + #endregion + } +} diff --git a/src/Umbraco.Core/Composing/IFactory.cs b/src/Umbraco.Core/Composing/IFactory.cs index 3e8cdf08e0..b753b3a1df 100644 --- a/src/Umbraco.Core/Composing/IFactory.cs +++ b/src/Umbraco.Core/Composing/IFactory.cs @@ -64,5 +64,13 @@ namespace Umbraco.Core.Composing /// Scopes can be nested. Each instance is disposed individually. /// IDisposable BeginScope(); + + /// + /// Enables per-request scope. + /// + /// + /// Ties scopes to web requests. + /// + void EnablePerWebRequestScope(); } } diff --git a/src/Umbraco.Core/Composing/IRegister.cs b/src/Umbraco.Core/Composing/IRegister.cs index 1ce7ae9f0b..747f3447b6 100644 --- a/src/Umbraco.Core/Composing/IRegister.cs +++ b/src/Umbraco.Core/Composing/IRegister.cs @@ -66,14 +66,6 @@ namespace Umbraco.Core.Composing /// void ConfigureForWeb(); - /// - /// Enables per-request scope. - /// - /// - /// Ties scopes to web requests. - /// - void EnablePerWebRequestScope(); - /// /// Creates the factory. /// diff --git a/src/Umbraco.Core/Composing/Lifetime.cs b/src/Umbraco.Core/Composing/Lifetime.cs index a7ae1d4179..e1b9950c39 100644 --- a/src/Umbraco.Core/Composing/Lifetime.cs +++ b/src/Umbraco.Core/Composing/Lifetime.cs @@ -8,21 +8,42 @@ /// /// Always get a new instance. /// + /// Corresponds to Transient in LightInject, Castle Windsor + /// or MS.DI, PerDependency in Autofac. Transient, /// /// One unique instance per request. /// + // fixme - not what you think! + // currently, corresponds to 'Request' in LightInject which is 'Transient + disposed by Scope' + // but NOT (in LightInject) a per-web-request lifetime, more a TransientScoped + // + // we use it for controllers, httpContextBase and umbracoContext + // - so that they are automatically disposed at the end of the scope (ie request) + // - not sure they should not be simply 'scoped'? + // + // Castle has an extra PerWebRequest something, and others use scope + // what about Request before first request ie during application startup? + // see http://blog.ploeh.dk/2009/11/17/UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7/ + // Castle ends up requiring a special scope manager too + // see https://groups.google.com/forum/#!topic/castle-project-users/1E2W9LVIYR4 + // + // but maybe also - why are we requiring scoped services at startup? Request, /// /// One unique instance per container scope. /// + /// Corresponds to Scope in LightInject, Scoped in MS.DI + /// or Castle Windsor, PerLifetimeScope in Autofac. Scope, /// /// One unique instance per container. /// + /// Corresponds to Singleton in LightInject, Castle Windsor + /// or MS.DI and to SingleInstance in Autofac. Singleton } } diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index d94643e49a..58bc8d2d44 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -145,10 +145,8 @@ namespace Umbraco.Core.Composing.LightInject break; case Lifetime.Request: case Lifetime.Scope: - Container.Register(serviceType, GetLifetime(lifetime)); - break; case Lifetime.Singleton: - Container.RegisterSingleton(serviceType); + Container.Register(serviceType, GetLifetime(lifetime)); break; default: throw new NotSupportedException($"Lifetime {lifetime} is not supported."); @@ -165,10 +163,8 @@ namespace Umbraco.Core.Composing.LightInject break; case Lifetime.Request: case Lifetime.Scope: - Container.Register(serviceType, implementingType, GetLifetime(lifetime)); - break; case Lifetime.Singleton: - Container.RegisterSingleton(serviceType, implementingType); + Container.Register(serviceType, implementingType, GetLifetime(lifetime)); break; default: throw new NotSupportedException($"Lifetime {lifetime} is not supported."); @@ -185,10 +181,8 @@ namespace Umbraco.Core.Composing.LightInject break; case Lifetime.Request: case Lifetime.Scope: - Container.Register(f => factory(this), GetLifetime(lifetime)); - break; case Lifetime.Singleton: - Container.RegisterSingleton(f => factory(this)); + Container.Register(f => factory(this), GetLifetime(lifetime)); break; default: throw new NotSupportedException($"Lifetime {lifetime} is not supported."); diff --git a/src/Umbraco.Core/Exceptions/LightInjectException.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectException.cs similarity index 96% rename from src/Umbraco.Core/Exceptions/LightInjectException.cs rename to src/Umbraco.Core/Composing/LightInject/LightInjectException.cs index 03fd9f2f9f..fa0aed21ca 100644 --- a/src/Umbraco.Core/Exceptions/LightInjectException.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectException.cs @@ -1,9 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Text; -namespace Umbraco.Core.Exceptions +namespace Umbraco.Core.Composing.LightInject { /// /// Represents errors that occur due to LightInject. diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs deleted file mode 100644 index d9651ef1a1..0000000000 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectExtensions.cs +++ /dev/null @@ -1,199 +0,0 @@ -using System; -using System.Linq; -using LightInject; - -namespace Umbraco.Core.Composing.LightInject -{ - /// - /// Provides extensions to LightInject. - /// - public static class LightInjectExtensions - { - /// - /// Registers the TService with the factory that describes the dependencies of the service, as a singleton. - /// - public static void RegisterSingleton(this IServiceRegistry container, Func factory, string serviceName) - { - var registration = container.GetAvailableService(serviceName); - if (registration == null) - { - container.Register(factory, serviceName, new PerContainerLifetime()); - } - else - { - if (registration.Lifetime is PerContainerLifetime == false) - throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, null, factory); - } - } - - /// - /// Registers a service with an implementation as a singleton. - /// - public static void RegisterSingleton(this IServiceRegistry container) - where TImplementation : TService - { - container.RegisterSingleton(typeof(TService), typeof(TImplementation)); - } - - /// - /// Registers a service with an implementation as a singleton. - /// - public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType) - { - var registration = container.GetAvailableService(serviceType); - - if (registration == null) - { - container.Register(serviceType, implementingType, new PerContainerLifetime()); - } - else - { - if (registration.Lifetime is PerContainerLifetime == false) - throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, implementingType, null); - } - } - - /// - /// Registers a service with a named implementation as a singleton. - /// - public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType, string name) - { - var registration = container.AvailableServices.FirstOrDefault(x => x.ServiceType == serviceType && x.ServiceName == name); - - if (registration == null) - { - container.Register(serviceType, implementingType, name, new PerContainerLifetime()); - } - else - { - if (registration.Lifetime is PerContainerLifetime == false) - throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, implementingType, null); - } - } - - /// - /// Registers a concrete type as a singleton service. - /// - public static void RegisterSingleton(this IServiceRegistry container) - { - container.RegisterSingleton(typeof(TImplementation)); - } - - /// - /// Registers a concrete type as a singleton service. - /// - public static void RegisterSingleton(this IServiceRegistry container, Type serviceType) - { - var registration = container.GetAvailableService(serviceType); - if (registration == null) - { - container.Register(serviceType, new PerContainerLifetime()); - } - else - { - if (registration.Lifetime is PerContainerLifetime == false) - throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, serviceType, null); - } - } - - /// - /// Registers the TService with the factory that describes the dependencies of the service, as a singleton. - /// - /// - /// - /// - public static void RegisterSingleton(this IServiceRegistry container, Func factory) - { - var registration = container.GetAvailableService(); - if (registration == null) - container.Register(factory, new PerContainerLifetime()); - else - UpdateRegistration(registration, null, factory); - } - - // note - what's below ALSO applies to non-singleton ie transient services - // - // see https://github.com/seesharper/LightInject/issues/133 - // - // note: we *could* use tracking lifetimes for singletons to ensure they have not been resolved - // already but that would not work for transient as the transient lifetime is null (and that is - // optimized in LightInject) - // - // also, RegisterSingleton above is dangerous because ppl could still use Register with a - // PerContainerLifetime and it will not work + the default Register would not work either for other - // lifetimes - // - // all in all, not sure we want to let ppl have direct access to the container - // we might instead want to expose some methods in UmbracoComponentBase or whatever? - - /// - /// Updates a registration. - /// - private static void UpdateRegistration(ServiceRegistration registration, Type implementingType, Delegate factoryExpression) - { - // if the container has compiled already then the registrations have been captured, - // and re-registering - although updating available services - does not modify the - // output of GetInstance - // - // so we have to rely on different methods - // - // assuming the service has NOT been resolved, both methods below work, but the first - // one looks simpler. it would be good to check whether the service HAS been resolved - // but I am not sure how to do it right now, depending on the lifetime - // - // if the service HAS been resolved then updating is probably a bad idea - - // not sure which is best? that one works, though, and looks simpler - registration.ImplementingType = implementingType; - registration.FactoryExpression = factoryExpression; - - //container.Override( - // r => r.ServiceType == typeof (TService) && (registration.ServiceName == null || r.ServiceName == registration.ServiceName), - // (f, r) => - // { - // r.ImplementingType = implementingType; - // r.FactoryExpression = factoryExpression; - // return r; - // }); - } - - /// - /// Gets the unique available service registration for a service type. - /// - /// The service type. - /// The container. - /// The unique service registration for the service type. - /// Can return null, but throws if more than one registration exist for the service type. - private static ServiceRegistration GetAvailableService(this IServiceRegistry container) - { - var typeofTService = typeof(TService); - return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService); - } - - /// - /// Gets the unique available service registration for a service type. - /// - private static ServiceRegistration GetAvailableService(this IServiceRegistry container, Type serviceType) - { - return container.AvailableServices.SingleOrDefault(x => x.ServiceType == serviceType); - } - - /// - /// Gets the unique available service registration for a service type and a name. - /// - /// The service type. - /// The container. - /// The name. - /// The unique service registration for the service type and the name. - /// Can return null, but throws if more than one registration exist for the service type and the name. - private static ServiceRegistration GetAvailableService(this IServiceRegistry container, string name) - { - var typeofTService = typeof(TService); - return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService && x.ServiceName == name); - } - } -} diff --git a/src/Umbraco.Core/Composing/RegisterExtensions.cs b/src/Umbraco.Core/Composing/RegisterExtensions.cs index cff51a7f53..4db1a2e9e4 100644 --- a/src/Umbraco.Core/Composing/RegisterExtensions.cs +++ b/src/Umbraco.Core/Composing/RegisterExtensions.cs @@ -1,7 +1,4 @@ -using System; -using Umbraco.Core.IO; - -namespace Umbraco.Core.Composing +namespace Umbraco.Core.Composing { /// /// Provides extension methods to the class. @@ -20,24 +17,6 @@ namespace Umbraco.Core.Composing public static void Register(this IRegister register, Lifetime lifetime = Lifetime.Transient) => register.Register(typeof(TService), lifetime); - /// - /// Registers a singleton service as its own implementation. - /// - public static void RegisterSingleton(this IRegister register) - => register.Register(typeof(TService), Lifetime.Singleton); - - /// - /// Registers a singleton service with an implementation type. - /// - public static void RegisterSingleton(this IRegister register) - => register.Register(typeof(TService), typeof(TImplementing), Lifetime.Singleton); - - /// - /// Registers a singleton service with an implementation factory. - /// - public static void RegisterSingleton(this IRegister register, Func factory) - => register.Register(factory, Lifetime.Singleton); - /// /// Registers a service with an implementing instance. /// @@ -49,44 +28,5 @@ namespace Umbraco.Core.Composing /// public static void RegisterAuto(this IRegister register) => register.RegisterAuto(typeof(TServiceBase)); - - /// - /// Registers a filesystem. - /// - /// The type of the filesystem. - /// The implementing type. - /// The register. - /// A factory method creating the supporting filesystem. - /// The register. - public static IRegister RegisterFileSystem(this IRegister register, Func supportingFileSystemFactory) - where TImplementing : FileSystemWrapper, TFileSystem - { - register.RegisterSingleton(factory => - { - var fileSystems = factory.GetInstance(); - return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); - }); - - return register; - } - - /// - /// Registers a filesystem. - /// - /// The type of the filesystem. - /// The register. - /// A factory method creating the supporting filesystem. - /// The register. - public static IRegister RegisterFileSystem(this IRegister register, Func supportingFileSystemFactory) - where TFileSystem : FileSystemWrapper - { - register.RegisterSingleton(factory => - { - var fileSystems = factory.GetInstance(); - return fileSystems.GetFileSystem(supportingFileSystemFactory(factory)); - }); - - return register; - } } } diff --git a/src/Umbraco.Core/IRuntime.cs b/src/Umbraco.Core/IRuntime.cs index 8a62e76a5e..d433dde12d 100644 --- a/src/Umbraco.Core/IRuntime.cs +++ b/src/Umbraco.Core/IRuntime.cs @@ -11,7 +11,8 @@ namespace Umbraco.Core /// Boots the runtime. /// /// The application register. - void Boot(IRegister register); + /// The application factory. + IFactory Boot(IRegister register); /// /// Gets the runtime state. diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 9ccb45cf0f..978c4f2906 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -44,19 +44,16 @@ namespace Umbraco.Core.Runtime public IRuntimeState State => _state; /// - public virtual void Boot(IRegister register) + public virtual IFactory Boot(IRegister register) { // create and register the essential services // ie the bare minimum required to boot // loggers var logger = GetLogger(); - register.RegisterInstance(logger); Logger = logger; var profiler = GetProfiler(); - register.RegisterInstance(profiler); var profilingLogger = new ProfilingLogger(logger, profiler); - register.RegisterInstance(profilingLogger); ProfilingLogger = profilingLogger; // application environment @@ -66,19 +63,14 @@ namespace Umbraco.Core.Runtime // application caches var appCaches = GetAppCaches(); - register.RegisterInstance(appCaches); var runtimeCache = appCaches.RuntimeCache; - register.RegisterInstance(runtimeCache); // database factory var databaseFactory = GetDatabaseFactory(); - register.RegisterInstance(databaseFactory); - register.RegisterSingleton(_ => databaseFactory.SqlContext); // type loader var globalSettings = UmbracoConfig.For.GlobalSettings(); var typeLoader = new TypeLoader(runtimeCache, globalSettings, profilingLogger); - register.RegisterInstance(typeLoader); // runtime state // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' @@ -90,11 +82,20 @@ namespace Umbraco.Core.Runtime { Level = RuntimeLevel.Boot }; - register.RegisterInstance(_state); // create the composition var composition = new Composition(register, typeLoader, profilingLogger, RuntimeLevel.Boot); + composition.RegisterUnique(logger); + composition.RegisterUnique(profiler); + composition.RegisterUnique(profilingLogger); + composition.RegisterUnique(appCaches); + composition.RegisterUnique(runtimeCache); + composition.RegisterUnique(databaseFactory); + composition.RegisterUnique(_ => databaseFactory.SqlContext); + composition.RegisterUnique(typeLoader); + composition.RegisterUnique(_state); + // register runtime-level services Compose(composition); @@ -120,7 +121,7 @@ namespace Umbraco.Core.Runtime logger.Debug("Runtime: {Runtime}", GetType().FullName); var mainDom = AquireMainDom(); - register.RegisterInstance(mainDom); + composition.RegisterUnique(mainDom); DetermineRuntimeLevel(databaseFactory); @@ -129,7 +130,7 @@ namespace Umbraco.Core.Runtime _components.Compose(); - _factory = Current.Factory = register.CreateFactory(); + _factory = Current.Factory = composition.CreateFactory(); _components.Initialize(_factory); } @@ -147,6 +148,8 @@ namespace Umbraco.Core.Runtime // throw a BootFailedException for every requests. } } + + return _factory; } protected virtual void ConfigureUnhandledException() diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 72d6d37010..83405dc13a 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -48,16 +48,16 @@ namespace Umbraco.Core.Runtime composition.WithCollectionBuilder().AddCoreMappers(); // register the scope provider - composition.RegisterSingleton(); // implements both IScopeProvider and IScopeAccessor - composition.RegisterSingleton(f => f.GetInstance()); - composition.RegisterSingleton(f => f.GetInstance()); + composition.RegisterUnique(); // implements both IScopeProvider and IScopeAccessor + composition.RegisterUnique(f => f.GetInstance()); + composition.RegisterUnique(f => f.GetInstance()); // register database builder // *not* a singleton, don't want to keep it around composition.Register(); // register manifest parser, will be injected in collection builders where needed - composition.RegisterSingleton(); + composition.RegisterUnique(); // register our predefined validators composition.WithCollectionBuilder() @@ -71,11 +71,11 @@ namespace Umbraco.Core.Runtime // properties and parameters derive from data editors composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetDataEditors()); - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); // register a server registrar, by default it's the db registrar - composition.RegisterSingleton(f => + composition.RegisterUnique(f => { if ("true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"])) return new SingleServerRegistrar(f.GetInstance()); @@ -87,7 +87,7 @@ namespace Umbraco.Core.Runtime // by default we'll use the database server messenger with default options (no callbacks), // this will be overridden by either the legacy thing or the db thing in the corresponding // components in the web project - fixme - should obsolete the legacy thing - composition.RegisterSingleton(factory + composition.RegisterUnique(factory => new DatabaseServerMessenger( factory.GetInstance(), factory.GetInstance(), @@ -105,9 +105,9 @@ namespace Umbraco.Core.Runtime composition.WithCollectionBuilder() .Append(composition.TypeLoader.GetTypes()); - composition.RegisterSingleton(); + composition.RegisterUnique(); - composition.RegisterSingleton(factory + composition.RegisterUnique(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); composition.WithCollectionBuilder() @@ -116,10 +116,10 @@ namespace Umbraco.Core.Runtime composition.WithCollectionBuilder() .Add(() => composition.TypeLoader.GetTypes()); - composition.RegisterSingleton(factory => new MigrationBuilder(factory)); + composition.RegisterUnique(factory => new MigrationBuilder(factory)); // by default, register a noop factory - composition.RegisterSingleton(); + composition.RegisterUnique(); } internal void Initialize(IEnumerable mapperProfiles) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index bc092271b7..4823811566 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -177,6 +177,7 @@ + @@ -188,7 +189,6 @@ - @@ -573,7 +573,7 @@ - + diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index a57ab93f3c..a70a3062b0 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -27,13 +27,13 @@ namespace Umbraco.Tests.Cache.DistributedCache var composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - register.Register(_ => new TestServerRegistrar()); - register.RegisterSingleton(_ => new TestServerMessenger()); + composition.RegisterUnique(_ => new TestServerRegistrar()); + composition.RegisterUnique(_ => new TestServerMessenger()); composition.WithCollectionBuilder() .Add(); - Current.Factory = register.CreateFactory(); + Current.Factory = composition.CreateFactory(); _distributedCache = new Umbraco.Web.Cache.DistributedCache(); } diff --git a/src/Umbraco.Tests/Composing/ContainerConfirmingTests.cs b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs similarity index 80% rename from src/Umbraco.Tests/Composing/ContainerConfirmingTests.cs rename to src/Umbraco.Tests/Composing/ContainerConformingTests.cs index fd76dbe8bb..aace92a956 100644 --- a/src/Umbraco.Tests/Composing/ContainerConfirmingTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs @@ -3,16 +3,15 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; namespace Umbraco.Tests.Composing { [TestFixture] - public class ContainerConfirmingTests + public class ContainerConformingTests { // tests that a container conforms - private IRegister GetRegister() => LightInjectContainer.Create(); + private IRegister GetRegister() => RegisterFactory.Create(); [Test] public void CanRegisterAndGet() @@ -144,10 +143,16 @@ namespace Umbraco.Tests.Composing } [Test] - public void SingletonServiceIsUnique() + public void SingletonServiceIsUnique() // fixme - but what is LightInject actually doing { var register = GetRegister(); + // fixme + // LightInject is 'unique' per serviceType+serviceName + // but that's not how all containers work + // and we should not rely on it + // if we need unique, use RegisterUnique + // for Core services that ppl may want to redefine in components, // it is important to be able to have a unique, singleton implementation, // and to redefine it - how it's done at container's level depends @@ -183,6 +188,40 @@ namespace Umbraco.Tests.Composing Assert.IsNull(factory.TryGetInstance()); } + [Test] + public void ActualInstanceIsNotUnique() + { + var register = GetRegister(); + + // define two instances + register.RegisterInstance(typeof(Thing1), new Thing1()); + register.RegisterInstance(typeof(Thing1), new Thing2()); + + var factory = register.CreateFactory(); + + var things = factory.GetInstance>(); + Assert.AreEqual(2, things.Count()); + + Assert.IsNull(factory.TryGetInstance()); + } + + [Test] + public void InterfaceInstanceIsNotUnique() + { + var register = GetRegister(); + + // define two instances + register.RegisterInstance(typeof(IThing), new Thing1()); + register.RegisterInstance(typeof(IThing), new Thing2()); + + var factory = register.CreateFactory(); + + var things = factory.GetInstance>(); + Assert.AreEqual(2, things.Count()); + + Assert.IsNull(factory.TryGetInstance()); + } + [Test] public void CanInjectEnumerableOfBase() { @@ -216,7 +255,7 @@ namespace Umbraco.Tests.Composing public void CanRegisterSingletonInterface() { var register = GetRegister(); - register.RegisterSingleton(); + register.Register(Lifetime.Singleton); var factory = register.CreateFactory(); var s1 = factory.GetInstance(); var s2 = factory.GetInstance(); @@ -227,7 +266,7 @@ namespace Umbraco.Tests.Composing public void CanRegisterSingletonClass() { var register = GetRegister(); - register.RegisterSingleton(); + register.Register(Lifetime.Singleton); var factory = register.CreateFactory(); var s1 = factory.GetInstance(); var s2 = factory.GetInstance(); @@ -238,8 +277,8 @@ namespace Umbraco.Tests.Composing public void CanReRegisterSingletonInterface() { var register = GetRegister(); - register.RegisterSingleton(); - register.RegisterSingleton(); + register.Register(Lifetime.Singleton); + register.Register(Lifetime.Singleton); var factory = register.CreateFactory(); var s = factory.GetInstance(); Assert.IsInstanceOf(s); @@ -249,7 +288,7 @@ namespace Umbraco.Tests.Composing public void CanRegisterSingletonWithCreate() { var register = GetRegister(); - register.RegisterSingleton(c => c.CreateInstance(new Thing1())); + register.Register(c => c.CreateInstance(new Thing1()), Lifetime.Singleton); var factory = register.CreateFactory(); var s1 = factory.GetInstance(); var s2 = factory.GetInstance(); diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 1f08e60375..180ecb7d42 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Composing composition.WithCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); - Current.Factory = container.CreateFactory(); + Current.Factory = composition.CreateFactory(); var actions = Current.PackageActions; Assert.AreEqual(2, actions.Count()); diff --git a/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs b/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs index d997a1bebd..c7741deb04 100644 --- a/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs +++ b/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs @@ -3,7 +3,6 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; -using Umbraco.Core.Composing; using Umbraco.Tests.Testing; namespace Umbraco.Tests.CoreThings @@ -18,7 +17,7 @@ namespace Umbraco.Tests.CoreThings var settings = SettingsForTests.GetDefaultUmbracoSettings(); // fixme - base should do it! - Composition.RegisterSingleton(_ => new DefaultShortStringHelper(settings)); + Composition.RegisterUnique(_ => new DefaultShortStringHelper(settings)); } [Test] diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index be1964cd72..d6ddac88d4 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -4,12 +4,10 @@ using System.Text; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Composing; using Umbraco.Core.Composing.Composers; -using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Logging; @@ -38,7 +36,7 @@ namespace Umbraco.Tests.IO composition.Register(_ => Mock.Of()); composition.Register(_ => Mock.Of()); composition.Register(_ => Mock.Of()); - composition.RegisterSingleton(); + composition.RegisterUnique(); composition.ComposeFileSystems(); diff --git a/src/Umbraco.Tests/Integration/ContentEventsTests.cs b/src/Umbraco.Tests/Integration/ContentEventsTests.cs index c138e48bfe..bb0556a0a8 100644 --- a/src/Umbraco.Tests/Integration/ContentEventsTests.cs +++ b/src/Umbraco.Tests/Integration/ContentEventsTests.cs @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Integration base.Compose(); Composition.Register(_ => new TestServerRegistrar()); // localhost-only - Composition.RegisterSingleton(); + Composition.RegisterUnique(); Composition.WithCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index c908cca64e..1f7c5624bf 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -3,9 +3,7 @@ using System.Collections.Generic; using System.Linq; using AutoMapper; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Composing; using Umbraco.Core.Manifest; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; @@ -28,7 +26,7 @@ namespace Umbraco.Tests.Models.Mapping { Path = TestHelper.CurrentAssemblyDirectory }; - Composition.Register(_ => manifestBuilder); + Composition.RegisterUnique(_ => manifestBuilder); Func> typeListProducerList = Enumerable.Empty; Composition.WithCollectionBuilder() diff --git a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs index d272dc9453..2c99bfeff1 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentTypeModelMappingTests.cs @@ -1,11 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; using AutoMapper; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -55,13 +53,13 @@ namespace Umbraco.Tests.Models.Mapping var dataEditors = new DataEditorCollection(editors); _editorsMock = new Mock(dataEditors); _editorsMock.Setup(x => x[It.IsAny()]).Returns(editors[0]); - Composition.RegisterSingleton(f => _editorsMock.Object); + Composition.RegisterUnique(f => _editorsMock.Object); - Composition.RegisterSingleton(_ => _contentTypeService.Object); - Composition.RegisterSingleton(_ => _contentService.Object); - Composition.RegisterSingleton(_ => _dataTypeService.Object); - Composition.RegisterSingleton(_ => _entityService.Object); - Composition.RegisterSingleton(_ => _fileService.Object); + Composition.RegisterUnique(_ => _contentTypeService.Object); + Composition.RegisterUnique(_ => _contentService.Object); + Composition.RegisterUnique(_ => _dataTypeService.Object); + Composition.RegisterUnique(_ => _entityService.Object); + Composition.RegisterUnique(_ => _fileService.Object); } [Test] diff --git a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs index df375aca13..cab9de9204 100644 --- a/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/ContentWebModelMappingTests.cs @@ -12,7 +12,6 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Core.Composing; using Umbraco.Tests.Testing; using Current = Umbraco.Web.Composing.Current; @@ -26,7 +25,7 @@ namespace Umbraco.Tests.Models.Mapping { base.Compose(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(f => Mock.Of()); } [DataEditor("Test.Test", "Test", "~/Test.html")] @@ -158,7 +157,7 @@ namespace Umbraco.Tests.Models.Mapping AssertBasicProperty(invariantContent, p); AssertDisplayProperty(invariantContent, p); } - + Assert.AreEqual(content.PropertyGroups.Count(), invariantContent.Tabs.Count()); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs index 8109ffbf56..9c326b3ddc 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PartialViewRepositoryTests.cs @@ -1,8 +1,6 @@ using System.Linq; using Moq; using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -29,7 +27,7 @@ namespace Umbraco.Tests.Persistence.Repositories { base.Compose(); - Composition.RegisterSingleton(f => new DataEditorCollection(Enumerable.Empty())); + Composition.RegisterUnique(f => new DataEditorCollection(Enumerable.Empty())); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs index 4a07b3780c..36c1bbdfb4 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs @@ -3,8 +3,6 @@ using System.Linq; using System.Text; using Moq; using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -39,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Repositories { base.Compose(); - Composition.RegisterSingleton(f => new DataEditorCollection(Enumerable.Empty())); + Composition.RegisterUnique(f => new DataEditorCollection(Enumerable.Empty())); } [Test] diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 1a869183bb..e801721f6b 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -74,7 +74,7 @@ namespace Umbraco.Tests.PropertyEditors composition.WithCollectionBuilder(); - Current.Factory = container.CreateFactory(); + Current.Factory = composition.CreateFactory(); var logger = Mock.Of(); var scheme = Mock.Of(); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index 2d2f1e8be7..e78ebb7eb1 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -3,7 +3,9 @@ using System.Threading; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; @@ -22,11 +24,12 @@ namespace Umbraco.Tests.PropertyEditors Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; var register = RegisterFactory.Create(); + var composition = new Composition(register, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); register.Register(_ => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GetDefaultUmbracoSettings()))); - Current.Factory = register.CreateFactory(); + Current.Factory = composition.CreateFactory(); } [TearDown] diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 0937c5ea70..b0be7b5eb6 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -189,7 +189,7 @@ namespace Umbraco.Tests.Published }); register.Register(f => factory); - Current.Factory = register.CreateFactory(); + Current.Factory = composition.CreateFactory(); var cacheMock = new Mock(); var cacheContent = new Dictionary(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs index 1d9247810f..7a96f670e6 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs @@ -2,13 +2,10 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Reflection; using Moq; using NUnit.Framework; -using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Tests.Testing; using Umbraco.Web; @@ -23,7 +20,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.RegisterSingleton(_ => GetServiceContext()); + Composition.RegisterUnique(_ => GetServiceContext()); } protected ServiceContext GetServiceContext() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs index 70faf18bf4..6b280832da 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentSnapshotTestBase.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Collections.ObjectModel; using System.Web.Routing; using Moq; using Umbraco.Core.Models.PublishedContent; @@ -10,7 +9,6 @@ using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Core.Composing; using Current = Umbraco.Core.Composing.Current; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; @@ -39,7 +37,7 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); + Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); } protected override TypeLoader CreateTypeLoader(IRuntimeCacheProvider runtimeCache, IGlobalSettings globalSettings, IProfilingLogger logger) diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index b347f0d676..914956dce1 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -33,9 +33,9 @@ namespace Umbraco.Tests.PublishedContent { base.Compose(); - Composition.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); - Composition.RegisterSingleton(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); + Composition.RegisterUnique(); + Composition.RegisterUnique(); var logger = Mock.Of(); var dataTypeService = new TestObjects.TestDataTypeService( @@ -45,7 +45,7 @@ namespace Umbraco.Tests.PublishedContent new DataType(new IntegerPropertyEditor(logger)) { Id = 1003 }, new DataType(new TextboxPropertyEditor(logger)) { Id = 1004 }, new DataType(new MediaPickerPropertyEditor(logger)) { Id = 1005 }); - Composition.RegisterSingleton(f => dataTypeService); + Composition.RegisterUnique(f => dataTypeService); } protected override void Initialize() diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 949031cc65..84f4f5dbd7 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -48,17 +48,8 @@ namespace Umbraco.Tests.Routing : base(umbracoApplication) { } - public override void Boot(IRegister container) - { - // do it before anything else - this is the only place where it's possible - var logger = Mock.Of(); - container.RegisterInstance(logger); - var profiler = Mock.Of(); - container.RegisterInstance(profiler); - container.RegisterInstance(new ProfilingLogger(logger, profiler)); - - base.Boot(container); - } + protected override ILogger GetLogger() => Mock.Of(); + protected override IProfiler GetProfiler() => Mock.Of(); } protected override void Compose() @@ -69,12 +60,12 @@ namespace Umbraco.Tests.Routing Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! var surfaceControllerTypes = new SurfaceControllerTypeCollection(Composition.TypeLoader.GetSurfaceControllers()); - Composition.RegisterInstance(surfaceControllerTypes); + Composition.RegisterUnique(surfaceControllerTypes); var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Composition.TypeLoader.GetUmbracoApiControllers()); - Composition.RegisterInstance(umbracoApiControllerTypes); + Composition.RegisterUnique(umbracoApiControllerTypes); - Composition.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); + Composition.RegisterUnique(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); } public override void TearDown() diff --git a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs index 100e814c83..7566c5372d 100644 --- a/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs +++ b/src/Umbraco.Tests/Routing/UrlRoutingTestBase.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Composition.RegisterSingleton(_ => GetServiceContext()); + Composition.RegisterUnique(_ => GetServiceContext()); } protected ServiceContext GetServiceContext() diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index 4ff732db01..3c6358f427 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Composition.RegisterSingleton(_ => Mock.Of()); + Composition.RegisterUnique(_ => Mock.Of()); Composition.Register(); } diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index e2c55b1003..13ec434608 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Routing protected override void Compose() { base.Compose(); - Composition.RegisterSingleton(_ => Mock.Of()); + Composition.RegisterUnique(_ => Mock.Of()); Composition.Register(); } diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 092ed54a35..2ef6480193 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -131,15 +131,16 @@ namespace Umbraco.Tests.Runtimes It.IsAny())) .Returns(Mock.Of()); - composition.RegisterInstance(scopeProvider); + composition.RegisterUnique(scopeProvider); } private MainDom _mainDom; - public override void Boot(IRegister container) + public override IFactory Boot(IRegister container) { - base.Boot(container); - _mainDom = Current.Factory.GetInstance(); + var factory = base.Boot(container); + _mainDom = factory.GetInstance(); + return factory; } public override void Terminate() @@ -184,7 +185,7 @@ namespace Umbraco.Tests.Runtimes base.Compose(composition); composition.Register(factory => SettingsForTests.GetDefaultUmbracoSettings()); - composition.RegisterSingleton(); + composition.RegisterUnique(); Composed = true; } diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index 933d8e9f7e..6a1a7272e7 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -38,10 +38,10 @@ namespace Umbraco.Tests.Scoping _testObjects = new TestObjects(register); - register.RegisterSingleton(factory => new FileSystems(factory, factory.TryGetInstance())); + composition.RegisterUnique(factory => new FileSystems(factory, factory.TryGetInstance())); composition.WithCollectionBuilder(); - Current.Factory = register.CreateFactory(); + Current.Factory = composition.CreateFactory(); SettingsForTests.Reset(); // ensure we have configuration } diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 1ab6f8d392..6e173128e3 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -44,8 +44,8 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // fixme - and we cannot inject a DistributedCache yet // so doing all this mess - Composition.RegisterSingleton(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(); + Composition.RegisterUnique(f => Mock.Of()); Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 815da6e6a6..0f990427ac 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -30,8 +30,8 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // fixme - and we cannot inject a DistributedCache yet // so doing all this mess - Composition.RegisterSingleton(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(); + Composition.RegisterUnique(f => Mock.Of()); Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs index 8855bc5a13..912dd317d7 100644 --- a/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedXmlTests.cs @@ -32,8 +32,8 @@ namespace Umbraco.Tests.Scoping // but then, it requires a lot of plumbing ;( // fixme - and we cannot inject a DistributedCache yet // so doing all this mess - Composition.RegisterSingleton(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(); + Composition.RegisterUnique(f => Mock.Of()); Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 9b33b1d30d..6b925ecb22 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -57,7 +57,7 @@ namespace Umbraco.Tests.Services { base.Compose(); - Composition.RegisterSingleton(factory => Mock.Of()); + Composition.RegisterUnique(factory => Mock.Of()); } /// @@ -279,7 +279,7 @@ namespace Umbraco.Tests.Services c.ContentSchedule.Add(now.AddSeconds(5), null); //release in 5 seconds var r = ServiceContext.ContentService.Save(c); Assert.IsTrue(r.Success, r.Result.ToString()); - } + } else { c.ContentSchedule.Add(null, now.AddSeconds(5)); //expire in 5 seconds @@ -315,7 +315,7 @@ namespace Umbraco.Tests.Services variant.Add(c); } - + var runSched = ServiceContext.ContentService.PerformScheduledPublish( now.AddMinutes(1)).ToList(); //process anything scheduled before a minute from now @@ -1305,7 +1305,7 @@ namespace Umbraco.Tests.Services public void Can_Unpublish_Content_Variation() { // Arrange - + var langUk = new Language("en-GB") { IsDefault = true }; var langFr = new Language("fr-FR"); @@ -1629,7 +1629,7 @@ namespace Umbraco.Tests.Services foreach (var x in descendants) Console.WriteLine(" ".Substring(0, x.Level) + x.Id); } - + Console.WriteLine(); // publish parent & its branch @@ -1983,7 +1983,7 @@ namespace Umbraco.Tests.Services var descendants = new List(); while(page * pageSize < total) descendants.AddRange(contentService.GetPagedDescendants(content.Id, page++, pageSize, out total)); - + Assert.AreNotEqual(-20, content.ParentId); Assert.IsFalse(content.Trashed); Assert.AreEqual(3, descendants.Count); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index 5cd1cdd1bc..94d2126bd2 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -35,8 +34,8 @@ namespace Umbraco.Tests.Services base.Compose(); // pfew - see note in ScopedNuCacheTests? - Composition.RegisterSingleton(); - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(); + Composition.RegisterUnique(f => Mock.Of()); Composition.WithCollectionBuilder() .Add(() => Composition.TypeLoader.GetCacheRefreshers()); } diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index b64b4dbf16..0ceaffa916 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -69,7 +69,7 @@ namespace Umbraco.Tests.Strings })); // fixme - move to a "compose" thing? - Composition.RegisterSingleton(f => _helper); + Composition.RegisterUnique(f => _helper); } private static readonly Regex FrenchElisionsRegex = new Regex("\\b(c|d|j|l|m|n|qu|s|t)('|\u8217)", RegexOptions.Compiled | RegexOptions.IgnoreCase); diff --git a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs index bcb6f0d60d..349648dd98 100644 --- a/src/Umbraco.Tests/Strings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/Strings/StringExtensionsTests.cs @@ -1,15 +1,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.Linq; -using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; namespace Umbraco.Tests.Strings @@ -17,12 +13,10 @@ namespace Umbraco.Tests.Strings [TestFixture] public class StringExtensionsTests : UmbracoTestBase { - public override void SetUp() + protected override void Compose() { - base.SetUp(); - - // fixme - in "compose"? - Composition.RegisterSingleton(_ => new MockShortStringHelper()); + base.Compose(); + Composition.RegisterUnique(_ => new MockShortStringHelper()); } [Test] diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 9dd8324e9f..a88438efce 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -35,23 +35,23 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); var container = RegisterFactory.Create(); - + var composition = new Composition(container, new TypeLoader(), Mock.Of(), RuntimeLevel.Run); - container.RegisterSingleton(_ => Mock.Of()); - container.RegisterSingleton(_ => Mock.Of()); + composition.RegisterUnique(_ => Mock.Of()); + composition.RegisterUnique(_ => Mock.Of()); var logger = new ProfilingLogger(Mock.Of(), Mock.Of()); var pluginManager = new TypeLoader(NullCacheProvider.Instance, SettingsForTests.GenerateMockGlobalSettings(), logger, false); - container.RegisterInstance(pluginManager); + composition.RegisterUnique(pluginManager); composition.WithCollectionBuilder() .Add(() => Current.TypeLoader.GetAssignedMapperTypes()); - var factory = Current.Factory = container.CreateFactory(); + var factory = Current.Factory = composition.CreateFactory(); Mappers = factory.GetInstance(); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index 832bbd141d..d969f8c3d3 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -27,8 +27,8 @@ namespace Umbraco.Tests.TestHelpers { base.Compose(); - Composition.RegisterSingleton(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); + Composition.RegisterUnique(); } protected override void Initialize() diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 72468f89b8..2daf86796b 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -80,7 +80,7 @@ namespace Umbraco.Tests.TestHelpers .Clear() .Add(() => Composition.TypeLoader.GetDataEditors()); - Composition.RegisterSingleton(f => + Composition.RegisterUnique(f => { if (Options.Database == UmbracoTestOptions.Database.None) return TestObjects.GetDatabaseFactoryMock(); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 67fa8361ba..72da9e9ef2 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -130,17 +130,18 @@ namespace Umbraco.Tests.Testing var register = RegisterFactory.Create(); - register.RegisterInstance(typeLoader); - register.RegisterInstance(logger); - register.RegisterInstance(profiler); - register.RegisterInstance(proflogger); - register.RegisterInstance(cacheHelper); - register.RegisterInstance(cacheHelper.RuntimeCache); - Composition = new Composition(register, typeLoader, proflogger, RuntimeLevel.Run); + + Composition.RegisterUnique(typeLoader); + Composition.RegisterUnique(logger); + Composition.RegisterUnique(profiler); + Composition.RegisterUnique(proflogger); + Composition.RegisterUnique(cacheHelper); + Composition.RegisterUnique(cacheHelper.RuntimeCache); + TestObjects = new TestObjects(register); Compose(); - Current.Factory = Factory = register.CreateFactory(); + Current.Factory = Factory = Composition.CreateFactory(); Initialize(); } @@ -209,11 +210,11 @@ namespace Umbraco.Tests.Testing Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); // web - Composition.Register(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); - Composition.RegisterSingleton(); + Composition.RegisterUnique(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); + Composition.RegisterUnique(); Composition.WithCollectionBuilder(); - Composition.Register(); - Composition.Register(); + Composition.RegisterUnique(); + Composition.RegisterUnique(); } protected virtual void ComposeWtf() @@ -221,14 +222,14 @@ namespace Umbraco.Tests.Testing // what else? var runtimeStateMock = new Mock(); runtimeStateMock.Setup(x => x.Level).Returns(RuntimeLevel.Run); - Composition.RegisterSingleton(f => runtimeStateMock.Object); + Composition.RegisterUnique(f => runtimeStateMock.Object); // ah... Composition.WithCollectionBuilder(); Composition.WithCollectionBuilder(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); // register empty content apps collection Composition.WithCollectionBuilder(); @@ -299,58 +300,58 @@ namespace Umbraco.Tests.Testing Composition.ComposeRepositories(); // register basic stuff that might need to be there for some container resolvers to work - Composition.RegisterSingleton(factory => umbracoSettings); - Composition.RegisterSingleton(factory => globalSettings); - Composition.RegisterSingleton(factory => umbracoSettings.Content); - Composition.RegisterSingleton(factory => umbracoSettings.Templates); - Composition.RegisterSingleton(factory => umbracoSettings.WebRouting); + Composition.RegisterUnique(factory => umbracoSettings); + Composition.RegisterUnique(factory => globalSettings); + Composition.RegisterUnique(factory => umbracoSettings.Content); + Composition.RegisterUnique(factory => umbracoSettings.Templates); + Composition.RegisterUnique(factory => umbracoSettings.WebRouting); - Composition.RegisterSingleton(factory => ExamineManager.Instance); + Composition.RegisterUnique(factory => ExamineManager.Instance); // register filesystems - Composition.RegisterSingleton(factory => TestObjects.GetFileSystemsMock()); + Composition.RegisterUnique(factory => TestObjects.GetFileSystemsMock()); var logger = Mock.Of(); var scheme = Mock.Of(); var config = Mock.Of(); var mediaFileSystem = new MediaFileSystem(Mock.Of(), config, scheme, logger); - Composition.RegisterSingleton(factory => mediaFileSystem); + Composition.RegisterUnique(factory => mediaFileSystem); // no factory (noop) - Composition.RegisterSingleton(); + Composition.RegisterUnique(); // register application stuff (database factory & context, services...) Composition.WithCollectionBuilder() .AddCoreMappers(); - Composition.RegisterSingleton(_ => new TransientEventMessagesFactory()); - Composition.RegisterSingleton(f => new UmbracoDatabaseFactory( + Composition.RegisterUnique(_ => new TransientEventMessagesFactory()); + Composition.RegisterUnique(f => new UmbracoDatabaseFactory( Constants.System.UmbracoConnectionName, Logger, new Lazy(Mock.Of))); - Composition.RegisterSingleton(f => f.TryGetInstance().SqlContext); + Composition.RegisterUnique(f => f.TryGetInstance().SqlContext); Composition.WithCollectionBuilder(); // empty - Composition.RegisterSingleton(factory + Composition.RegisterUnique(factory => TestObjects.GetScopeProvider(factory.TryGetInstance(), factory.TryGetInstance(), factory.TryGetInstance())); - Composition.RegisterSingleton(factory => (IScopeAccessor) factory.GetInstance()); + Composition.RegisterUnique(factory => (IScopeAccessor) factory.GetInstance()); Composition.ComposeServices(); // composition root is doing weird things, fix - Composition.RegisterSingleton(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); + Composition.RegisterUnique(); // somehow property editor ends up wanting this Composition.WithCollectionBuilder(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); // note - don't register collections, use builders Composition.WithCollectionBuilder(); - Composition.RegisterSingleton(); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); + Composition.RegisterUnique(); } #endregion diff --git a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs index 91f2cef961..1f4a01fd3d 100644 --- a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs +++ b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs @@ -3,8 +3,6 @@ using NUnit.Framework; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using System; -using System.Linq; -using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Tests.Testing; using Umbraco.Web.Services; @@ -22,7 +20,7 @@ namespace Umbraco.Tests.TreesAndSections protected override void Compose() { base.Compose(); - Composition.Register(); + Composition.RegisterUnique(); } public override void SetUp() diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index c84aef7256..09e8cd312d 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -116,7 +116,7 @@ - + diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index eea755455d..5be3fe2e7e 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.UmbracoExamine { base.Compose(); - Composition.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); + Composition.RegisterUnique(_ => new DefaultShortStringHelper(SettingsForTests.GetDefaultUmbracoSettings())); } } } diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs index 8aae044c55..ec97b92c8e 100644 --- a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs @@ -81,14 +81,14 @@ namespace Umbraco.Tests.Web.Controllers var textService = new Mock(); textService.Setup(x => x.Localize(It.IsAny(), It.IsAny(), It.IsAny>())).Returns(""); - Composition.RegisterSingleton(f => Mock.Of()); - Composition.RegisterSingleton(f => userServiceMock.Object); - Composition.RegisterSingleton(f => entityService.Object); - Composition.RegisterSingleton(f => dataTypeService.Object); - Composition.RegisterSingleton(f => langService.Object); - Composition.RegisterSingleton(f => textService.Object); - Composition.RegisterSingleton(f => Mock.Of()); - Composition.RegisterSingleton(f => new UmbracoApiControllerTypeCollection(new[] { typeof(ContentTreeController) })); + Composition.RegisterUnique(f => Mock.Of()); + Composition.RegisterUnique(f => userServiceMock.Object); + Composition.RegisterUnique(f => entityService.Object); + Composition.RegisterUnique(f => dataTypeService.Object); + Composition.RegisterUnique(f => langService.Object); + Composition.RegisterUnique(f => textService.Object); + Composition.RegisterUnique(f => Mock.Of()); + Composition.RegisterUnique(f => new UmbracoApiControllerTypeCollection(new[] { typeof(ContentTreeController) })); } private MultipartFormDataContent GetMultiPartRequestContent(string json) diff --git a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs index d62cf7b93c..857e922ac9 100644 --- a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs @@ -38,12 +38,12 @@ namespace Umbraco.Tests.Web.Controllers // replace the true IUserService implementation with a mock // so that each test can configure the service to their liking - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(f => Mock.Of()); // kill the true IEntityService too - Composition.RegisterSingleton(f => Mock.Of()); + Composition.RegisterUnique(f => Mock.Of()); - Composition.RegisterSingleton(); + Composition.RegisterUnique(); } [Test] diff --git a/src/Umbraco.Web/Components/NotificationsComponent.cs b/src/Umbraco.Web/Components/NotificationsComponent.cs index b54dce4e3e..685029f038 100644 --- a/src/Umbraco.Web/Components/NotificationsComponent.cs +++ b/src/Umbraco.Web/Components/NotificationsComponent.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.Components public override void Compose(Composition composition) { base.Compose(composition); - composition.RegisterSingleton(); + composition.RegisterUnique(); } public void Initialize(INotificationService notificationService, Notifier notifier, ActionCollection actions) diff --git a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs index ae7f769753..103cd32912 100644 --- a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.Composing.LightInject public override void ConfigureForWeb() { // IoC setup for LightInject for MVC/WebApi - // see comments on MixedLightInjectScopeManagerProvider for explainations of what we are doing here + // see comments on MixedLightInjectScopeManagerProvider for explanations of what we are doing here if (!(Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); Container.EnableMvc(); // does container.EnablePerWebRequestScope() diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index 7725fe6524..91aceebdc0 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -8,7 +8,6 @@ using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.ContentApps; -using Umbraco.Web.Features; // the namespace here is intentional - although defined in Umbraco.Web assembly, // this class should be visible when using Umbraco.Core.Components, alongside @@ -80,7 +79,7 @@ namespace Umbraco.Core.Components #endregion - #region Singletons + #region Uniques /// /// Sets the content last chance finder. @@ -90,7 +89,7 @@ namespace Umbraco.Core.Components public static void SetContentLastChanceFinder(this Composition composition) where T : IContentLastChanceFinder { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -100,7 +99,7 @@ namespace Umbraco.Core.Components /// A function creating a last chance finder. public static void SetContentLastChanceFinder(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -110,7 +109,7 @@ namespace Umbraco.Core.Components /// A last chance finder. public static void SetContentLastChanceFinder(this Composition composition, IContentLastChanceFinder finder) { - composition.RegisterSingleton(_ => finder); + composition.RegisterUnique(_ => finder); } /// @@ -131,7 +130,7 @@ namespace Umbraco.Core.Components public static void SetPublishedSnapshotService(this Composition composition) where T : IPublishedSnapshotService { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -141,7 +140,7 @@ namespace Umbraco.Core.Components /// A function creating a published snapshot service. public static void SetPublishedSnapshotService(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -151,7 +150,7 @@ namespace Umbraco.Core.Components /// A published snapshot service. public static void SetPublishedSnapshotService(this Composition composition, IPublishedSnapshotService service) { - composition.RegisterSingleton(_ => service); + composition.RegisterUnique(_ => service); } /// @@ -162,7 +161,7 @@ namespace Umbraco.Core.Components public static void SetSiteDomainHelper(this Composition composition) where T : ISiteDomainHelper { - composition.RegisterSingleton(); + composition.RegisterUnique(); } /// @@ -172,7 +171,7 @@ namespace Umbraco.Core.Components /// A function creating a helper. public static void SetSiteDomainHelper(this Composition composition, Func factory) { - composition.RegisterSingleton(factory); + composition.RegisterUnique(factory); } /// @@ -182,7 +181,7 @@ namespace Umbraco.Core.Components /// A helper. public static void SetSiteDomainHelper(this Composition composition, ISiteDomainHelper helper) { - composition.RegisterSingleton(_ => helper); + composition.RegisterUnique(_ => helper); } #endregion diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 621bab282d..525a8abf77 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Runtime } /// - public override void Boot(IRegister register) + public override IFactory Boot(IRegister register) { // create and start asap to profile boot var debug = GlobalSettings.DebugMode; @@ -44,10 +44,15 @@ namespace Umbraco.Web.Runtime _webProfiler = new VoidProfiler(); } - base.Boot(register); + var factory = base.Boot(register); - // now (and only now) is the time to switch over to perWebRequest scopes - register.EnablePerWebRequestScope(); + // now (and only now) is the time to switch over to perWebRequest scopes. + // up until that point we may not have a request, and scoped services would + // fail to resolve - but we run Initialize within a factory scope - and then, + // here, we switch the factory to bind scopes to requests + factory.EnablePerWebRequestScope(); + + return factory; } /// @@ -58,7 +63,7 @@ namespace Umbraco.Web.Runtime // some components may want to initialize with the UmbracoApplicationBase // well, they should not - we should not do this // TODO remove this eventually. - composition.RegisterInstance(_umbracoApplication); + composition.RegisterUnique(_umbracoApplication); } #region Getters diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index e5973b24bc..1e5dd51c7d 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -66,7 +66,7 @@ namespace Umbraco.Web.Runtime composition.Register(); - composition.RegisterSingleton(); // required for hybrid accessors + composition.RegisterUnique(); // required for hybrid accessors composition.ComposeWebMappingProfiles(); @@ -81,21 +81,21 @@ namespace Umbraco.Web.Runtime composition.Register(); // register accessors for cultures - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); // 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.RegisterSingleton(); + composition.RegisterUnique(); // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request composition.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), Lifetime.Request); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context - composition.RegisterSingleton(); + composition.RegisterUnique(); // 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 @@ -104,21 +104,22 @@ namespace Umbraco.Web.Runtime composition.Register(factory => factory.GetInstance().UmbracoContext, Lifetime.Request); // register the umbraco helper - composition.RegisterSingleton(); + composition.RegisterUnique(); // register distributed cache - composition.RegisterSingleton(f => new DistributedCache()); + composition.RegisterUnique(f => new DistributedCache()); // replace some services - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); - composition.RegisterSingleton(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); - composition.RegisterSingleton(factory => ExamineManager.Instance); + composition.RegisterUnique(factory => ExamineManager.Instance); // configure the container for web composition.ConfigureForWeb(); + composition .ComposeMvcControllers(GetType().Assembly) .ComposeApiControllers(GetType().Assembly); @@ -131,7 +132,7 @@ namespace Umbraco.Web.Runtime composition.WithCollectionBuilder(); - composition.RegisterSingleton(); + composition.RegisterUnique(); // set the default RenderMvcController Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG! @@ -140,10 +141,10 @@ namespace Umbraco.Web.Runtime .Add(() => composition.TypeLoader.GetTypes()); var surfaceControllerTypes = new SurfaceControllerTypeCollection(composition.TypeLoader.GetSurfaceControllers()); - composition.RegisterInstance(surfaceControllerTypes); + composition.RegisterUnique(surfaceControllerTypes); var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(composition.TypeLoader.GetUmbracoApiControllers()); - composition.RegisterInstance(umbracoApiControllerTypes); + composition.RegisterUnique(umbracoApiControllerTypes); // both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be // discovered when CoreBootManager configures the converters. We HAVE to remove one of them @@ -165,7 +166,7 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - composition.RegisterSingleton(); + composition.RegisterUnique(); composition.WithCollectionBuilder() // all built-in finders in the correct order, @@ -177,9 +178,9 @@ namespace Umbraco.Web.Runtime .Append() .Append(); - composition.RegisterSingleton(); + composition.RegisterUnique(); - composition.RegisterSingleton(); + composition.RegisterUnique(); // register *all* checks, except those marked [HideFromTypeFinder] of course composition.WithCollectionBuilder() @@ -192,14 +193,14 @@ namespace Umbraco.Web.Runtime composition.RegisterAuto(typeof(UmbracoViewPage<>)); // register published router - composition.RegisterSingleton(); + composition.RegisterUnique(); composition.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); // register preview SignalR hub - composition.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); + composition.RegisterUnique(_ => GlobalHost.ConnectionManager.GetHubContext()); // register properties fallback - composition.RegisterSingleton(); + composition.RegisterUnique(); // register known content apps composition.WithCollectionBuilder() diff --git a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs index e0e47ca666..984ba85522 100644 --- a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs +++ b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs @@ -2,7 +2,6 @@ using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; -using Umbraco.Core.Composing; using Umbraco.Core.Sync; using Umbraco.Web.Cache; @@ -14,7 +13,7 @@ namespace Umbraco.Web.SignalR public override void Compose(Composition composition) { base.Compose(composition); - composition.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); + composition.RegisterUnique(_ => GlobalHost.ConnectionManager.GetHubContext()); } // using a lazy arg here means that we won't create the hub until necessary diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index 7b8fa56201..650229a21b 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web /// /// Gets the application register. /// - protected virtual IRegister GetContainer() + protected virtual IRegister GetRegister() { return RegisterFactory.Create(); } @@ -58,11 +58,11 @@ namespace Umbraco.Web { // ******** THIS IS WHERE EVERYTHING BEGINS ******** - // create the container for the application, and boot + // create the register for the application, and boot // the boot manager is responsible for registrations - var container = GetContainer(); + var register = GetRegister(); _runtime = GetRuntime(); - _runtime.Boot(container); + _runtime.Boot(register); } // called by ASP.NET (auto event wireup) once per app domain