From 5836cd05cbf7085c5f44a3e3c756cc44d56a5837 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 20 Jul 2018 15:45:01 +0200 Subject: [PATCH] Abstract container (in progress) --- src/Umbraco.Core/Components/BootLoader.cs | 14 +- src/Umbraco.Core/Components/Composition.cs | 6 +- .../Components/CompositionExtensions.cs | 14 +- .../Composing/CollectionBuilderBase.cs | 2 +- .../Composers/ConfigurationComposer.cs | 17 +- .../Composers/CoreMappingProfilesComposer.cs | 9 +- .../Composers/FileSystemsComposer.cs | 15 +- .../Composers/RepositoriesComposer.cs | 81 +++--- .../Composing/Composers/ServicesComposer.cs | 127 ++++----- src/Umbraco.Core/Composing/Current.cs | 3 +- src/Umbraco.Core/Composing/IContainer.cs | 87 +++++- src/Umbraco.Core/Composing/Lifetime.cs | 28 ++ .../LightInject/LightInjectContainer.cs | 226 +++++++++++++++- .../Composing/LightInjectExtensions.cs | 252 ++++-------------- src/Umbraco.Core/ContainerExtensions.cs | 29 +- src/Umbraco.Core/IRuntime.cs | 6 +- .../Migrations/MigrationBuilder.cs | 5 +- src/Umbraco.Core/Runtime/CoreRuntime.cs | 10 +- .../Runtime/CoreRuntimeComponent.cs | 3 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 + src/Umbraco.Core/UmbracoApplicationBase.cs | 18 +- .../DistributedCache/DistributedCacheTests.cs | 8 +- .../PublishedMediaCacheTests.cs | 2 - .../Components/ComponentTests.cs | 6 +- .../Composing/CollectionBuildersTests.cs | 31 ++- .../Composing/LazyCollectionBuilderTests.cs | 6 + .../Composing/PackageActionCollectionTests.cs | 5 +- src/Umbraco.Tests/CoreThings/UdiTests.cs | 6 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 10 +- .../Models/Mapping/AutoMapperTests.cs | 2 - src/Umbraco.Tests/Models/VariationTests.cs | 6 +- .../PropertyEditors/ImageCropperTest.cs | 11 +- .../PropertyEditorValueEditorTests.cs | 6 +- .../Published/ConvertersTests.cs | 6 +- .../PublishedContentMoreTests.cs | 5 +- .../PublishedContentTestBase.cs | 3 - .../PublishedContent/PublishedContentTests.cs | 5 +- .../Routing/ContentFinderByIdTests.cs | 2 +- .../ContentFinderByUrlAndTemplateTests.cs | 2 - .../Routing/RenderRouteHandlerTests.cs | 5 +- .../Routing/UmbracoModuleTests.cs | 7 +- .../Runtimes/CoreRuntimeTests.cs | 6 +- .../Scoping/ScopeEventDispatcherTests.cs | 10 +- .../Scoping/ScopedRepositoryTests.cs | 1 + .../Services/ContentServiceTests.cs | 6 - .../Services/Importing/PackageImportTests.cs | 4 +- .../Strings/DefaultShortStringHelperTests.cs | 3 - .../TestHelpers/BaseUsingSqlCeSyntax.cs | 8 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 7 +- .../TestControllerActivatorBase.cs | 8 - .../TestHelpers/TestObjects-Mocks.cs | 8 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 14 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 28 +- .../UmbracoExamine/ExamineBaseTest.cs | 8 +- .../Web/Mvc/UmbracoViewPageTests.cs | 5 - .../Web/TemplateUtilitiesTests.cs | 8 +- ...aseServerRegistrarAndMessengerComponent.cs | 1 - .../Composers/ControllersComposer.cs} | 22 +- .../Composing/Composers/InstallerComposer.cs | 15 +- .../Composers/WebMappingProfilesComposer.cs | 59 ++-- .../LightInject/LightInjectContainer.cs | 32 +++ src/Umbraco.Web/CompositionExtensions.cs | 11 +- .../NuCache/NuCacheComponent.cs | 1 + .../XmlPublishedCache/XmlCacheComponent.cs | 1 - src/Umbraco.Web/Runtime/WebRuntime.cs | 12 +- .../Runtime/WebRuntimeComponent.cs | 23 +- .../SignalR/PreviewHubComponent.cs | 3 +- src/Umbraco.Web/Umbraco.Web.csproj | 3 +- src/Umbraco.Web/UmbracoApplication.cs | 6 + 69 files changed, 757 insertions(+), 643 deletions(-) create mode 100644 src/Umbraco.Core/Composing/Lifetime.cs rename src/Umbraco.Web/{LightInjectExtensions.cs => Composing/Composers/ControllersComposer.cs} (65%) create mode 100644 src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs index ee38864933..b80fa93500 100644 --- a/src/Umbraco.Core/Components/BootLoader.cs +++ b/src/Umbraco.Core/Components/BootLoader.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; -using LightInject; using Umbraco.Core.Collections; +using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Scoping; @@ -15,7 +15,7 @@ namespace Umbraco.Core.Components internal class BootLoader { - private readonly IServiceContainer _container; + private readonly IContainer _container; private readonly ProfilingLogger _proflog; private readonly ILogger _logger; private IUmbracoComponent[] _components; @@ -27,7 +27,7 @@ namespace Umbraco.Core.Components /// Initializes a new instance of the class. /// /// The application container. - public BootLoader(IServiceContainer container) + public BootLoader(IContainer container) { _container = container ?? throw new ArgumentNullException(nameof(container)); _proflog = container.GetInstance(); @@ -247,15 +247,16 @@ namespace Umbraco.Core.Components private static void GatherRequirementsFromRequiredAttribute(Type type, ICollection types, IDictionary> requirements) { // get 'required' attributes - // fixme explain + // these attributes are *not* inherited because we want to "custom-inherit" for interfaces only var requiredAttributes = type - .GetInterfaces().SelectMany(x => x.GetCustomAttributes()) - .Concat(type.GetCustomAttributes()); + .GetInterfaces().SelectMany(x => x.GetCustomAttributes()) // those marking interfaces + .Concat(type.GetCustomAttributes()); // those marking the component foreach (var attr in requiredAttributes) { if (attr.RequiringType == type) continue; // ignore self-requirements (+ exclude in implems, below) + // required by an interface = by any enabled component implementing this that interface if (attr.RequiringType.IsInterface) { var implems = types.Where(x => x != type && attr.RequiringType.IsAssignableFrom(x)).ToList(); @@ -265,6 +266,7 @@ namespace Umbraco.Core.Components requirements[implem].Add(type); } } + // required by a class else { if (types.Contains(attr.RequiringType)) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 671469c73a..91fa519694 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -1,4 +1,4 @@ -using LightInject; +using Umbraco.Core.Composing; namespace Umbraco.Core.Components { @@ -17,7 +17,7 @@ namespace Umbraco.Core.Components /// /// A container. /// The runtime level. - public Composition(IServiceContainer container, RuntimeLevel level) + public Composition(IContainer container, RuntimeLevel level) { Container = container; RuntimeLevel = level; @@ -27,7 +27,7 @@ namespace Umbraco.Core.Components /// Gets the container. /// /// Use with care! - public IServiceContainer Container { get; } + public IContainer Container { get; } /// /// Gets the runtime level. diff --git a/src/Umbraco.Core/Components/CompositionExtensions.cs b/src/Umbraco.Core/Components/CompositionExtensions.cs index 7e94e4dc2b..abc0fa3862 100644 --- a/src/Umbraco.Core/Components/CompositionExtensions.cs +++ b/src/Umbraco.Core/Components/CompositionExtensions.cs @@ -1,6 +1,4 @@ using System; -using System.Runtime.CompilerServices; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Dictionary; using Umbraco.Core.Composing; @@ -97,7 +95,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a culture dictionary factory. - public static void SetCultureDictionaryFactory(this Composition composition, Func factory) + public static void SetCultureDictionaryFactory(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -128,7 +126,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a published content model factory. - public static void SetPublishedContentModelFactory(this Composition composition, Func factory) + public static void SetPublishedContentModelFactory(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -159,7 +157,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a server registar. - public static void SetServerRegistrar(this Composition composition, Func factory) + public static void SetServerRegistrar(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -182,7 +180,7 @@ namespace Umbraco.Core.Components public static void SetServerMessenger(this Composition composition) where T : IServerMessenger { - composition.Container.RegisterSingleton(); + composition.Container.Register(Lifetime.Singleton); } /// @@ -190,7 +188,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a server messenger. - public static void SetServerMessenger(this Composition composition, Func factory) + public static void SetServerMessenger(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -221,7 +219,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a short string helper. - public static void SetShortStringHelper(this Composition composition, Func factory) + public static void SetShortStringHelper(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index 3fac2d3255..2dbefc860f 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -140,7 +140,7 @@ namespace Umbraco.Core.Composing var type = typeof (TItem); return _registrations - .Select(x => (TItem) Container.GetInstanceOrThrow(type, x.ServiceName, x.ImplementingType, args)) + .Select(x => (TItem) Container.GetInstance(type, x.ServiceName, args)) .ToArray(); // safe } diff --git a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs index e2ba477045..4e8f2ec65c 100644 --- a/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ConfigurationComposer.cs @@ -1,5 +1,4 @@ -using LightInject; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Core.Composing.Composers @@ -9,17 +8,17 @@ namespace Umbraco.Core.Composing.Composers /// public static class ConfigurationComposer { - public static IServiceRegistry ComposeConfiguration(this IServiceRegistry registry) + public static IContainer ComposeConfiguration(this IContainer container) { - registry.Register(factory => UmbracoConfig.For.UmbracoSettings()); - registry.Register(factory => factory.GetInstance().Content); - registry.Register(factory => factory.GetInstance().Templates); - registry.Register(factory => factory.GetInstance().RequestHandler); - registry.Register(factory => UmbracoConfig.For.GlobalSettings()); + container.Register(factory => UmbracoConfig.For.UmbracoSettings()); + container.Register(factory => factory.GetInstance().Content); + container.Register(factory => factory.GetInstance().Templates); + container.Register(factory => factory.GetInstance().RequestHandler); + container.Register(factory => UmbracoConfig.For.GlobalSettings()); // fixme - other sections we need to add? - return registry; + return container; } } } diff --git a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs index ce9f507b9f..a1fc36a8c4 100644 --- a/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/CoreMappingProfilesComposer.cs @@ -1,15 +1,14 @@ -using LightInject; -using Umbraco.Core.Models.Identity; +using Umbraco.Core.Models.Identity; namespace Umbraco.Core.Composing.Composers { public static class CoreMappingProfilesComposer { - public static IServiceRegistry ComposeCoreMappingProfiles(this IServiceRegistry registry) + public static IContainer ComposeCoreMappingProfiles(this IContainer container) { - registry.Register(); - return registry; + container.Register(); + return container; } } } diff --git a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs index c7ed93680b..565db9c623 100644 --- a/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/FileSystemsComposer.cs @@ -1,5 +1,4 @@ -using LightInject; -using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -7,22 +6,22 @@ namespace Umbraco.Core.Composing.Composers { public static class FileSystemsComposer { - public static IServiceRegistry ComposeFileSystems(this IServiceRegistry registry) + public static IContainer ComposeFileSystems(this IContainer container) { // register FileSystems, which manages all filesystems - registry.RegisterSingleton(); + container.RegisterSingleton(); // register IFileSystems, which gives access too all filesystems - registry.RegisterSingleton(factory => factory.GetInstance()); + container.RegisterSingleton(factory => factory.GetInstance()); // register MediaFileSystem, which can be injected directly - registry.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); + container.RegisterSingleton(factory => factory.GetInstance().MediaFileSystem); // register MediaFileSystem, so that FileSystems can create it - registry.Register((f, wrappedFileSystem) + container.Register((f, wrappedFileSystem) => new MediaFileSystem(wrappedFileSystem, f.GetInstance(), f.GetInstance(), f.GetInstance())); - return registry; + return container; } } } diff --git a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs index 79b2b9c223..25399af5c7 100644 --- a/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/RepositoriesComposer.cs @@ -1,5 +1,4 @@ -using LightInject; -using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; namespace Umbraco.Core.Composing.Composers @@ -9,48 +8,48 @@ namespace Umbraco.Core.Composing.Composers /// public static class RepositoriesComposer { - public static IServiceRegistry ComposeRepositories(this IServiceRegistry registry) + public static IContainer ComposeRepositories(this IContainer container) { // repositories - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); - return registry; + return container; } } } diff --git a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs index c774912f2e..fc898dd3b6 100644 --- a/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs +++ b/src/Umbraco.Core/Composing/Composers/ServicesComposer.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Linq; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Events; using Umbraco.Core.IO; @@ -13,83 +12,85 @@ namespace Umbraco.Core.Composing.Composers { public static class ServicesComposer { - public static IServiceRegistry ComposeServices(this IServiceRegistry registry) + public static IContainer ComposeServices(this IContainer container) { // register a transient messages factory, which will be replaced by the web // boot manager when running in a web context - registry.RegisterSingleton(); + container.RegisterSingleton(); // register the service context - registry.RegisterSingleton(); + container.RegisterSingleton(); // register the special idk map - registry.RegisterSingleton(); + container.RegisterSingleton(); // register the services - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.RegisterSingleton(); - registry.Register(factory => - { - var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); - var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); - var configLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config + "/lang/")); - - var pluginLangFolders = appPlugins.Exists == false - ? Enumerable.Empty() - : appPlugins.GetDirectories() - .SelectMany(x => x.GetDirectories("Lang")) - .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) - .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 5) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); - - //user defined langs that overwrite the default, these should not be used by plugin creators - var userLangFolders = configLangFolder.Exists == false - ? Enumerable.Empty() - : configLangFolder - .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) - .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 10) - .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); - - return new LocalizedTextServiceFileSources( - factory.GetInstance(), - factory.GetInstance().RuntimeCache, - mainLangFolder, - pluginLangFolders.Concat(userLangFolders)); - }); - registry.RegisterSingleton(factory => new LocalizedTextService( + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); + container.Register(SourcesFactory); + container.RegisterSingleton(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. - registry.RegisterSingleton(); - registry.RegisterSingleton(); + container.RegisterSingleton(); + container.RegisterSingleton(); - return registry; + return container; + } + + private static LocalizedTextServiceFileSources SourcesFactory(IContainer container) + { + var mainLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Umbraco + "/config/lang/")); + var appPlugins = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)); + var configLangFolder = new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config + "/lang/")); + + var pluginLangFolders = appPlugins.Exists == false + ? Enumerable.Empty() + : appPlugins.GetDirectories() + .SelectMany(x => x.GetDirectories("Lang")) + .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) + .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 5) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); + + //user defined langs that overwrite the default, these should not be used by plugin creators + var userLangFolders = configLangFolder.Exists == false + ? Enumerable.Empty() + : configLangFolder + .GetFiles("*.user.xml", SearchOption.TopDirectoryOnly) + .Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 10) + .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true)); + + return new LocalizedTextServiceFileSources( + container.GetInstance(), + container.GetInstance().RuntimeCache, + mainLangFolder, + pluginLangFolders.Concat(userLangFolders)); } } } diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs index fcff2c4b9e..d0025c0c8b 100644 --- a/src/Umbraco.Core/Composing/Current.cs +++ b/src/Umbraco.Core/Composing/Current.cs @@ -1,5 +1,4 @@ using System; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; @@ -20,7 +19,7 @@ namespace Umbraco.Core.Composing /// Provides a static service locator for most singletons. /// /// - /// This class is initialized with the container via LightInjectExtensions.ConfigureUmbracoCore, + /// This class is initialized with the container in UmbracoApplicationBase, /// right after the container is created in UmbracoApplicationBase.HandleApplicationStart. /// Obviously, this is a service locator, which some may consider an anti-pattern. And yet, /// practically, it works. diff --git a/src/Umbraco.Core/Composing/IContainer.cs b/src/Umbraco.Core/Composing/IContainer.cs index 7183a76af2..ba611063e2 100644 --- a/src/Umbraco.Core/Composing/IContainer.cs +++ b/src/Umbraco.Core/Composing/IContainer.cs @@ -1,11 +1,12 @@ using System; +using System.Collections.Generic; namespace Umbraco.Core.Composing { /// /// Defines a container for Umbraco. /// - public interface IContainer + public interface IContainer : IDisposable { /// /// Gets the concrete container. @@ -22,6 +23,15 @@ namespace Umbraco.Core.Composing /// Throws an exception if the container failed to get an instance of the specified type. object GetInstance(Type type); + /// + /// Gets a named instance. + /// + /// The type of the instance. + /// The name of the instance. + /// An instance of the specified type. + /// Throws an exception if the container failed to get an instance of the specified type. + object GetInstance(Type type, string name); + /// /// Gets an instance with arguments. /// @@ -44,16 +54,62 @@ namespace Umbraco.Core.Composing /// to get an instance of the specified type, but failed to do so. object TryGetInstance(Type type); + /// + /// Gets all instances of a service. + /// + /// The type of the service. + IEnumerable GetAllInstances(Type serviceType); + + /// + /// Gets all instances of a service. + /// + /// The type of the service. + IEnumerable GetAllInstances(); + #endregion #region Registry - // fixme register direct type? - // fixme register an instance? - void RegisterSingleton(Func factory); - void Register(Func factory); + /// + /// Registers a service as its own implementation. + /// + void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementation type. + /// + void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with a named implementation type. + /// + void Register(Type serviceType, Type implementingType, string name, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementation factory. + /// + void Register(Func factory, Lifetime lifetime = Lifetime.Transient); + + /// + /// Registers a service with an implementation factory accepting an argument. + /// void Register(Func factory); + /// + /// Registers a service with an implementing instance. + /// + void RegisterInstance(Type serviceType, object instance); + + /// + /// Registers a base type for auto-registration. + /// + void RegisterAuto(Type serviceBaseType); + + /// + /// Registers a service with an ordered set of implementation types. + /// + void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient); + /// /// Registers and instanciates a collection builder. /// @@ -62,5 +118,26 @@ namespace Umbraco.Core.Composing T RegisterCollectionBuilder(); #endregion + + #region Control + + /// + /// Begins a scope. + /// + /// + /// When the scope is disposed, scoped instances that have been created during the scope are disposed. + /// Scopes can be nested. Each instance is disposed individually. + /// + IDisposable BeginScope(); + + // fixme - document all these + + void ConfigureForUmbraco(); + + void ConfigureForWeb(); + + void EnablePerWebRequestScope(); + + #endregion } } diff --git a/src/Umbraco.Core/Composing/Lifetime.cs b/src/Umbraco.Core/Composing/Lifetime.cs new file mode 100644 index 0000000000..a7ae1d4179 --- /dev/null +++ b/src/Umbraco.Core/Composing/Lifetime.cs @@ -0,0 +1,28 @@ +namespace Umbraco.Core.Composing +{ + /// + /// Specifies the lifetime of a registered instance. + /// + public enum Lifetime + { + /// + /// Always get a new instance. + /// + Transient, + + /// + /// One unique instance per request. + /// + Request, + + /// + /// One unique instance per container scope. + /// + Scope, + + /// + /// One unique instance per container. + /// + Singleton + } +} diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 72ebda62ee..0cc7700888 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Reflection; using LightInject; namespace Umbraco.Core.Composing.LightInject @@ -8,45 +10,241 @@ namespace Umbraco.Core.Composing.LightInject /// public class LightInjectContainer : IContainer { - private readonly IServiceContainer _container; - /// /// Initializes a new instance of the with a LightInject container. /// - public LightInjectContainer(IServiceContainer container) + public LightInjectContainer(ServiceContainer container) { - _container = container; + Container = container; } + /// + /// Gets the LightInject container. + /// + protected ServiceContainer Container { get; } + /// - public object ConcreteContainer => _container; + public object ConcreteContainer => Container; + + /// + public void Dispose() + => Container.Dispose(); + + #region Factory /// public object GetInstance(Type type) - => _container.GetInstance(type); + => Container.GetInstance(type); + + /// + public object GetInstance(Type type, string name) + => Container.GetInstance(type, name); /// public object GetInstance(Type type, object[] args) - => _container.GetInstance(type, args); + => Container.GetInstance(type, args); /// public object TryGetInstance(Type type) - => _container.TryGetInstance(type); + => Container.TryGetInstance(type); /// - public void RegisterSingleton(Func factory) - => _container.RegisterSingleton(f => factory(this)); + public IEnumerable GetAllInstances() + => Container.GetAllInstances(); /// - public void Register(Func factory) - => _container.Register(f => factory(this)); + public IEnumerable GetAllInstances(Type type) + => Container.GetAllInstances(type); + + #endregion + + #region Registry + + /// + public void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient) + { + switch (lifetime) + { + case Lifetime.Transient: + case Lifetime.Request: + case Lifetime.Scope: + Container.Register(serviceType, GetLifetime(lifetime)); + break; + case Lifetime.Singleton: + Container.RegisterSingleton(serviceType); + break; + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } + + /// + public void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient) + { + switch (lifetime) + { + case Lifetime.Transient: + case Lifetime.Request: + case Lifetime.Scope: + Container.Register(serviceType, implementingType, GetLifetime(lifetime)); + break; + case Lifetime.Singleton: + Container.RegisterSingleton(serviceType, implementingType); + break; + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } + + /// + public void Register(Type serviceType, Type implementingType, string name, Lifetime lifetime = Lifetime.Transient) + { + switch (lifetime) + { + case Lifetime.Transient: + case Lifetime.Request: + case Lifetime.Scope: + Container.Register(serviceType, implementingType, name, GetLifetime(lifetime)); + break; + case Lifetime.Singleton: + Container.RegisterSingleton(serviceType, implementingType, name); + break; + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } + + /// + public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) + { + switch (lifetime) + { + case Lifetime.Transient: + case Lifetime.Request: + case Lifetime.Scope: + Container.Register(f => factory(this), GetLifetime(lifetime)); + break; + case Lifetime.Singleton: + Container.RegisterSingleton(f => factory(this)); + break; + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } /// public void Register(Func factory) - => _container.Register((f, x) => factory(this, x)); + => Container.Register((f, x) => factory(this, x)); + + private ILifetime GetLifetime(Lifetime lifetime) + { + switch (lifetime) + { + case Lifetime.Transient: + return null; + case Lifetime.Request: + return new PerRequestLifeTime(); + case Lifetime.Scope: + return new PerScopeLifetime(); + case Lifetime.Singleton: + return new PerContainerLifetime(); + default: + throw new NotSupportedException($"Lifetime {lifetime} is not supported."); + } + } + + /// + public void RegisterInstance(Type serviceType, object instance) + => Container.RegisterInstance(serviceType, instance); + + /// + public void RegisterAuto(Type serviceBaseType) + { + Container.RegisterFallback((serviceType, serviceName) => + { + // https://github.com/seesharper/LightInject/issues/173 + if (serviceBaseType.IsAssignableFromGtd(serviceType)) + Container.Register(serviceType); + return false; + }, null); + } + + /// + public void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient) + => Container.RegisterOrdered(serviceType, implementingTypes, _ => GetLifetime(lifetime)); /// public T RegisterCollectionBuilder() - => _container.RegisterCollectionBuilder(); + => Container.RegisterCollectionBuilder(); + + #endregion + + #region Control + + /// + public IDisposable BeginScope() + => Container.BeginScope(); + + /// + public void ConfigureForUmbraco() + { + // supports annotated constructor injections + // eg to specify the service name on some services + Container.EnableAnnotatedConstructorInjection(); + + // from the docs: "LightInject considers all read/write properties a dependency, but implements + // a loose strategy around property dependencies, meaning that it will NOT throw an exception + // in the case of an unresolved property dependency." + // + // in Umbraco we do NOT want to do property injection by default, so we have to disable it. + // from the docs, the following line will cause the container to "now only try to inject + // dependencies for properties that is annotated with the InjectAttribute." + // + // could not find it documented, but tests & code review shows that LightInject considers a + // property to be "injectable" when its setter exists and is not static, nor private, nor + // it is an index property. which means that eg protected or internal setters are OK. + Container.EnableAnnotatedPropertyInjection(); + + // ensure that we do *not* scan assemblies + // we explicitely RegisterFrom our own composition roots and don't want them scanned + Container.AssemblyScanner = new AssemblyScanner(/*container.AssemblyScanner*/); + + // see notes in MixedLightInjectScopeManagerProvider + Container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider(); + } + + private class AssemblyScanner : IAssemblyScanner + { + //private readonly IAssemblyScanner _scanner; + + //public AssemblyScanner(IAssemblyScanner scanner) + //{ + // _scanner = scanner; + //} + + public void Scan(Assembly assembly, IServiceRegistry serviceRegistry, Func lifetime, Func shouldRegister, Func serviceNameProvider) + { + // nothing - we *could* scan non-Umbraco assemblies, though + } + + public void Scan(Assembly assembly, IServiceRegistry serviceRegistry) + { + // nothing - we *could* scan non-Umbraco assemblies, though + } + } + + /// + public virtual void ConfigureForWeb() + { } + + /// + public void EnablePerWebRequestScope() + { + if (!(Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) + throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); + smp.EnablePerWebRequestScope(); + } + + #endregion } } diff --git a/src/Umbraco.Core/Composing/LightInjectExtensions.cs b/src/Umbraco.Core/Composing/LightInjectExtensions.cs index a64d3aff30..446b2850f7 100644 --- a/src/Umbraco.Core/Composing/LightInjectExtensions.cs +++ b/src/Umbraco.Core/Composing/LightInjectExtensions.cs @@ -12,107 +12,10 @@ namespace Umbraco.Core.Composing /// public static class LightInjectExtensions { - /// - /// Configure the container for Umbraco Core usage and assign to Current. - /// - /// The container. - /// The container is now the unique application container and is now accessible via Current.Container. - internal static void ConfigureUmbracoCore(this ServiceContainer container) + // fixme temp + internal static ServiceContainer AsLightInject(this IContainer container) { - // supports annotated constructor injections - // eg to specify the service name on some services - container.EnableAnnotatedConstructorInjection(); - - // from the docs: "LightInject considers all read/write properties a dependency, but implements - // a loose strategy around property dependencies, meaning that it will NOT throw an exception - // in the case of an unresolved property dependency." - // - // in Umbraco we do NOT want to do property injection by default, so we have to disable it. - // from the docs, the following line will cause the container to "now only try to inject - // dependencies for properties that is annotated with the InjectAttribute." - // - // could not find it documented, but tests & code review shows that LightInject considers a - // property to be "injectable" when its setter exists and is not static, nor private, nor - // it is an index property. which means that eg protected or internal setters are OK. - container.EnableAnnotatedPropertyInjection(); - - // ensure that we do *not* scan assemblies - // we explicitely RegisterFrom our own composition roots and don't want them scanned - container.AssemblyScanner = new AssemblyScanner(/*container.AssemblyScanner*/); - - // see notes in MixedLightInjectScopeManagerProvider - container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider(); - - // self-register - // fixme - WHERE is this used, and should it be a generic container, not LightInject's? - container.Register(_ => container); - - // configure the current container - Current.Container = new LightInject.LightInjectContainer(container); - } - - private class AssemblyScanner : IAssemblyScanner - { - //private readonly IAssemblyScanner _scanner; - - //public AssemblyScanner(IAssemblyScanner scanner) - //{ - // _scanner = scanner; - //} - - public void Scan(Assembly assembly, IServiceRegistry serviceRegistry, Func lifetime, Func shouldRegister, Func serviceNameProvider) - { - // nothing - we *could* scan non-Umbraco assemblies, though - } - - public void Scan(Assembly assembly, IServiceRegistry serviceRegistry) - { - // nothing - we *could* scan non-Umbraco assemblies, though - } - } - - /// - /// Registers a service implementation with a specified lifetime. - /// - /// The type of the service. - /// The type of the implementation. - /// The type of the lifetime. - /// The container. - public static void Register(this IServiceContainer container) - where TImplementation : TService - where TLifetime : ILifetime, new() - { - container.Register(new TLifetime()); - } - - /// - /// Registers a service implementation with a specified lifetime. - /// - /// The type of the service. - /// The type of the lifetime. - /// The container. - /// A factory. - public static void Register(this IServiceContainer container, Func factory) - where TLifetime : ILifetime, new() - { - container.Register(factory, new TLifetime()); - } - - /// - /// Registers several service implementations with a specified lifetime. - /// - /// The type of the service. - /// The type of the lifetime. - /// The container. - /// The types of the implementations. - public static void RegisterMany(this IServiceContainer container, IEnumerable implementations) - where TLifeTime : ILifetime, new() - { - foreach (var implementation in implementations) - { - // if "typeof (TService)" is there then "implementation.FullName" MUST be there too - container.Register(typeof(TService), implementation, implementation.FullName, new TLifeTime()); - } + return (ServiceContainer) container.ConcreteContainer; } /// @@ -139,17 +42,39 @@ namespace Umbraco.Core.Composing public static void RegisterSingleton(this IServiceRegistry container) where TImplementation : TService { - var registration = container.GetAvailableService(); + container.RegisterSingleton(typeof(TService), typeof(TImplementation)); + } + + // fixme + public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType) + { + var registration = container.GetAvailableService(serviceType); if (registration == null) { - container.Register(new PerContainerLifetime()); + container.Register(serviceType, implementingType, new PerContainerLifetime()); } else { if (registration.Lifetime is PerContainerLifetime == false) throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, typeof(TImplementation), null); + UpdateRegistration(registration, implementingType, null); + } + } + + public static void RegisterSingleton(this IServiceRegistry container, Type serviceType, Type implementingType, string name) + { + var registration = container.GetAvailableServices(serviceType).FirstOrDefault(x => 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); } } @@ -158,18 +83,22 @@ namespace Umbraco.Core.Composing /// public static void RegisterSingleton(this IServiceRegistry container) { - var registration = container.GetAvailableService(); + container.RegisterSingleton(typeof(TImplementation)); + } + + public static void RegisterSingleton(this IServiceRegistry container, Type serviceType) + { + var registration = container.GetAvailableService(serviceType); if (registration == null) { - container.Register(new PerContainerLifetime()); + container.Register(serviceType, new PerContainerLifetime()); } else { if (registration.Lifetime is PerContainerLifetime == false) throw new InvalidOperationException("Existing registration lifetime is not PerContainer."); - UpdateRegistration(registration, typeof(TImplementation), null); + UpdateRegistration(registration, serviceType, null); } - } /// @@ -240,10 +169,10 @@ namespace Umbraco.Core.Composing /// The container. /// The service registrations for the service type. public static IEnumerable GetAvailableServices(this IServiceRegistry container) - { - var typeofTService = typeof(TService); - return container.AvailableServices.Where(x => x.ServiceType == typeofTService); - } + => container.GetAvailableServices(typeof(TService)); + + public static IEnumerable GetAvailableServices(this IServiceRegistry container, Type serviceType) + => container.AvailableServices.Where(x => x.ServiceType == serviceType); /// /// Gets the unique available service registration for a service type. @@ -258,6 +187,12 @@ namespace Umbraco.Core.Composing return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService); } + // fixme + public 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. /// @@ -272,101 +207,6 @@ namespace Umbraco.Core.Composing return container.AvailableServices.SingleOrDefault(x => x.ServiceType == typeofTService && x.ServiceName == name); } - /// - /// Gets an instance of a TService or throws a meaningful exception. - /// - /// The service type. - /// The container. - /// The instance. - public static TService GetInstanceOrThrow(this IServiceFactory factory) - { - if (factory == null) - throw new ArgumentNullException(nameof(factory)); - - try - { - return factory.GetInstance(); - } - catch (Exception e) - { - LightInjectException.TryThrow(e); - throw; - } - } - - /// - /// Gets an instance of a TService or throws a meaningful exception. - /// - /// The container. - /// The type of the service. - /// The name of the service. - /// The implementing type. - /// Arguments. - /// The instance. - internal static object GetInstanceOrThrow(this IServiceFactory factory, Type tService, string serviceName, Type implementingType, object[] args) - { - if (factory == null) - throw new ArgumentNullException(nameof(factory)); - - // fixme temp - STOP doing this, it confuses LightInject and then we get ugly exception traces - // we HAVE to let LightInject throw - and catch at THE OUTERMOST if InvalidOperationException in LightInject.Anything! - - return factory.GetInstance(tService, serviceName, args); - //try - //{ - // return factory.GetInstance(tService, serviceName, args); - //} - //catch (Exception e) - //{ - // LightInjectException.TryThrow(e, implementingType); - // throw; - //} - } - - /// - /// Registers a base type for auto-registration. - /// - /// The base type. - /// The container. - /// - /// Any type that inherits/implements the base type will be auto-registered on-demand. - /// This methods works with actual types. Use the other overload for eg generic definitions. - /// - public static void RegisterAuto(this IServiceContainer container) - { - container.RegisterFallback((serviceType, serviceName) => - { - //Current.Logger.Debug(typeof(LightInjectExtensions), $"Fallback for type {serviceType.FullName}."); - // https://github.com/seesharper/LightInject/issues/173 - - if (typeof(T).IsAssignableFrom(serviceType)) - container.Register(serviceType); - return false; - }, null); - } - - /// - /// Registers a base type for auto-registration. - /// - /// The container. - /// The base type. - /// - /// Any type that inherits/implements the base type will be auto-registered on-demand. - /// This methods works with actual types, as well as generic definitions eg typeof(MyBase{}). - /// - public static void RegisterAuto(this IServiceContainer container, Type type) - { - container.RegisterFallback((serviceType, serviceName) => - { - //Current.Logger.Debug(typeof(LightInjectExtensions), $"Fallback for type {serviceType.FullName}."); - // https://github.com/seesharper/LightInject/issues/173 - - if (type.IsAssignableFromGtd(serviceType)) - container.Register(serviceType); - return false; - }, null); - } - /// /// Registers and instanciates a collection builder. /// diff --git a/src/Umbraco.Core/ContainerExtensions.cs b/src/Umbraco.Core/ContainerExtensions.cs index 351a3c26f1..ddaab485c1 100644 --- a/src/Umbraco.Core/ContainerExtensions.cs +++ b/src/Umbraco.Core/ContainerExtensions.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Composing; +using System; +using Umbraco.Core.Composing; namespace Umbraco.Core { @@ -41,5 +42,31 @@ namespace Umbraco.Core /// to get an instance of the specified type, but failed to do so. public static T TryGetInstance(this IContainer container) => (T) container.TryGetInstance(typeof(T)); + + // fixme - document all these + + public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) + => container.Register(typeof(TService), typeof(TImplementing), lifetime); + + public static void Register(this IContainer container, string name, Lifetime lifetime = Lifetime.Transient) + => container.Register(typeof(TService), typeof(TImplementing), name, lifetime); + + public static void Register(this IContainer container, Lifetime lifetime = Lifetime.Transient) + => container.Register(typeof(TService), lifetime); + + public static void RegisterSingleton(this IContainer container) + => container.Register(typeof(TService), Lifetime.Singleton); + + public static void RegisterSingleton(this IContainer container) + => container.Register(typeof(TService), typeof(TImplementing), Lifetime.Singleton); + + public static void RegisterSingleton(this IContainer container, Func factory) + => container.Register(factory, Lifetime.Singleton); + + public static void RegisterInstance(this IContainer container, TService instance) + => container.RegisterInstance(typeof(TService), instance); + + public static void RegisterAuto(this IContainer container) + => container.RegisterAuto(typeof(TServiceBase)); } } diff --git a/src/Umbraco.Core/IRuntime.cs b/src/Umbraco.Core/IRuntime.cs index 37b265ad77..f11bafbf2f 100644 --- a/src/Umbraco.Core/IRuntime.cs +++ b/src/Umbraco.Core/IRuntime.cs @@ -1,4 +1,4 @@ -using LightInject; +using Umbraco.Core.Composing; namespace Umbraco.Core { @@ -10,8 +10,8 @@ namespace Umbraco.Core /// /// Boots the runtime. /// - /// The application service container. - void Boot(ServiceContainer container); + /// The application container. + void Boot(IContainer container); /// /// Terminates the runtime. diff --git a/src/Umbraco.Core/Migrations/MigrationBuilder.cs b/src/Umbraco.Core/Migrations/MigrationBuilder.cs index 3d8c88c771..fb01afc35a 100644 --- a/src/Umbraco.Core/Migrations/MigrationBuilder.cs +++ b/src/Umbraco.Core/Migrations/MigrationBuilder.cs @@ -1,13 +1,14 @@ using System; using LightInject; +using Umbraco.Core.Composing; namespace Umbraco.Core.Migrations { public class MigrationBuilder : IMigrationBuilder { - private readonly IServiceContainer _container; + private readonly IContainer _container; - public MigrationBuilder(IServiceContainer container) + public MigrationBuilder(IContainer container) { _container = container; diff --git a/src/Umbraco.Core/Runtime/CoreRuntime.cs b/src/Umbraco.Core/Runtime/CoreRuntime.cs index 94004c6ae3..7ab87029a5 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntime.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.Threading; using System.Web; -using LightInject; using Umbraco.Core.Cache; using Umbraco.Core.Components; using Umbraco.Core.Composing; @@ -42,7 +40,7 @@ namespace Umbraco.Core.Runtime } /// - public virtual void Boot(ServiceContainer container) + public virtual void Boot(IContainer container) { // some components may want to initialize with the UmbracoApplicationBase // well, they should not - we should not do this @@ -114,7 +112,7 @@ namespace Umbraco.Core.Runtime //sa.Scope?.Dispose(); } - private void AquireMainDom(IServiceFactory container) + private void AquireMainDom(IContainer container) { using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Aquired.")) { @@ -132,7 +130,7 @@ namespace Umbraco.Core.Runtime } // internal for tests - internal void DetermineRuntimeLevel(IServiceFactory container) + internal void DetermineRuntimeLevel(IContainer container) { using (var timer = ProfilingLogger.DebugDuration("Determining runtime level.", "Determined.")) { @@ -185,7 +183,7 @@ namespace Umbraco.Core.Runtime /// /// Composes the runtime. /// - public virtual void Compose(ServiceContainer container) + public virtual void Compose(IContainer container) { // compose the very essential things that are needed to bootstrap, before anything else, // and only these things - the rest should be composed in runtime components diff --git a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs index 4d1fd28462..6320401681 100644 --- a/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs +++ b/src/Umbraco.Core/Runtime/CoreRuntimeComponent.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Configuration; -using System.IO; using AutoMapper; using LightInject; using Umbraco.Core.Cache; @@ -94,7 +93,7 @@ namespace Umbraco.Core.Runtime composition.Container.RegisterCollectionBuilder() .Append(factory => factory.GetInstance().GetTypes()); - composition.Container.Register(new PerContainerLifetime()); + composition.Container.RegisterSingleton(); composition.Container.RegisterSingleton(factory => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 6084580ff0..efea4bdd22 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -167,6 +167,7 @@ + diff --git a/src/Umbraco.Core/UmbracoApplicationBase.cs b/src/Umbraco.Core/UmbracoApplicationBase.cs index 9930f43ca4..98ddbc883f 100644 --- a/src/Umbraco.Core/UmbracoApplicationBase.cs +++ b/src/Umbraco.Core/UmbracoApplicationBase.cs @@ -4,7 +4,6 @@ using System.Threading; using System.Web; using System.Web.Hosting; using log4net; -using LightInject; using Umbraco.Core.Composing; using Umbraco.Core.Logging; @@ -30,6 +29,16 @@ namespace Umbraco.Core return Logger.CreateWithDefaultLog4NetConfiguration(); } + /// + /// Gets the application container. + /// + protected virtual IContainer GetContainer() + { + // note: the actual, web UmbracoApplication is overriding this + // with a web-supporting container + return new Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + } + // events - in the order they trigger // were part of the BootManager architecture, would trigger only for the initial @@ -60,8 +69,9 @@ namespace Umbraco.Core // create the container for the application, and configure. // the boot manager is responsible for registrations - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); // also sets Current.Container + var container = GetContainer(); + container.ConfigureForUmbraco(); + Current.Container = container; // register the essential stuff, // ie the global application logger @@ -163,7 +173,7 @@ namespace Umbraco.Core // dispose the container and everything // but first, capture the looger! var logger = Current.Logger; - Current.Reset(); + Current.Reset(); if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted) return; diff --git a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs index dc67bb532f..d8f3e615ec 100644 --- a/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/Cache/DistributedCache/DistributedCacheTests.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Sync; @@ -20,11 +20,11 @@ namespace Umbraco.Tests.Cache.DistributedCache [SetUp] public void Setup() { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); container.Register(_ => new TestServerRegistrar()); - container.Register(_ => new TestServerMessenger(), new PerContainerLifetime()); + container.RegisterSingleton(_ => new TestServerMessenger()); container.RegisterCollectionBuilder() .Add(); diff --git a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs index 64194ebb47..d0924aa1a6 100644 --- a/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs +++ b/src/Umbraco.Tests/Cache/PublishedCache/PublishedMediaCacheTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Xml; @@ -13,7 +12,6 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Web.PublishedCache.XmlPublishedCache; using Umbraco.Tests.Testing; using Current = Umbraco.Web.Composing.Current; -using LightInject; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Tests.PublishedContent; diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 995350f80e..b0e0d308b8 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Components; +using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -21,7 +21,7 @@ namespace Umbraco.Tests.Components private static readonly List Composed = new List(); private static readonly List Initialized = new List(); - private static IServiceContainer MockContainer(Action> setup = null) + private static IContainer MockContainer(Action> setup = null) { // fixme use IUmbracoDatabaseFactory vs UmbracoDatabaseFactory, clean it all up! @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Components var fs = new FileSystems(logger); var p = new ScopeProvider(f, fs, logger); - var mock = new Mock(); + var mock = new Mock(); mock.Setup(x => x.GetInstance(typeof (ILogger))).Returns(logger); mock.Setup(x => x.GetInstance(typeof (ProfilingLogger))).Returns(new ProfilingLogger(Mock.Of(), Mock.Of())); mock.Setup(x => x.GetInstance(typeof (IUmbracoDatabaseFactory))).Returns(f); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 87b0cd5173..3ab554b28e 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -1,24 +1,24 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using NUnit.Framework; using Umbraco.Core.Composing; +using Umbraco.Core; namespace Umbraco.Tests.Composing { [TestFixture] public class CollectionBuildersTests { - private ServiceContainer _container; + private IContainer _container; [SetUp] public void Setup() { Current.Reset(); - _container = new ServiceContainer(); - _container.ConfigureUmbracoCore(); + _container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + _container.ConfigureForUmbraco(); } [TearDown] @@ -344,24 +344,27 @@ namespace Umbraco.Tests.Composing // but the container manages the scope, so to test the scope // the collection must come from the container - var scope1 = _container.BeginScope(); + TestCollection col1A, col1B; + + using (_container.BeginScope()) + { + col1A = _container.GetInstance(); + col1B = _container.GetInstance(); + } - var col1A = _container.GetInstance(); AssertCollection(col1A, typeof(Resolved1), typeof(Resolved2)); - var col1B = _container.GetInstance(); AssertCollection(col1B, typeof(Resolved1), typeof(Resolved2)); - AssertSameCollection(col1A, col1B); - _container.ScopeManagerProvider.GetScopeManager(_container).CurrentScope.Dispose(); - var scope2 = _container.BeginScope(); + TestCollection col2; + + using (_container.BeginScope()) + { + col2 = _container.GetInstance(); + } - var col2 = _container.GetInstance(); AssertCollection(col2, typeof(Resolved1), typeof(Resolved2)); - AssertNotSameCollection(col1A, col2); - - _container.ScopeManagerProvider.GetScopeManager(_container).CurrentScope.Dispose(); } [Test] diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index 7a39186fea..a9b7dd5ba0 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -5,6 +5,7 @@ using LightInject; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; namespace Umbraco.Tests.Composing { @@ -32,6 +33,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add() @@ -56,6 +58,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) @@ -79,6 +82,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add() @@ -103,6 +107,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add() @@ -125,6 +130,7 @@ namespace Umbraco.Tests.Composing { var container = new ServiceContainer(); container.ConfigureUmbracoCore(); + Current.Container = new LightInjectContainer(container); container.RegisterCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index e2145f557a..0b318f80cf 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Xml; -using LightInject; using NUnit.Framework; using Umbraco.Core.Composing; using Umbraco.Core._Legacy.PackageActions; @@ -14,8 +13,8 @@ namespace Umbraco.Tests.Composing [Test] public void PackageActionCollectionBuilderWorks() { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); container.RegisterCollectionBuilder() .Add(() => TypeLoader.GetPackageActions()); diff --git a/src/Umbraco.Tests/CoreThings/UdiTests.cs b/src/Umbraco.Tests/CoreThings/UdiTests.cs index 49c02d5688..12ce3227e1 100644 --- a/src/Umbraco.Tests/CoreThings/UdiTests.cs +++ b/src/Umbraco.Tests/CoreThings/UdiTests.cs @@ -23,11 +23,11 @@ namespace Umbraco.Tests.CoreThings public void SetUp() { // fixme - bad in a unit test - but Udi has a static ctor that wants it?! - var container = new Mock(); + var container = new Mock(); var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); - container.Setup(x => x.GetInstance(typeof (TypeLoader))).Returns( + container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, globalSettings, new ProfilingLogger(Mock.Of(), Mock.Of()))); - Current.Container = new Core.Composing.LightInject.LightInjectContainer(container.Object); + Current.Container = container.Object; Udi.ResetUdiTypes(); } diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index f31b587062..75a41560cf 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Text; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -18,7 +17,7 @@ namespace Umbraco.Tests.IO [TestFixture] public class FileSystemsTests { - private ServiceContainer _container; + private IContainer _container; [SetUp] public void Setup() @@ -27,8 +26,9 @@ namespace Umbraco.Tests.IO var config = SettingsForTests.GetDefaultUmbracoSettings(); SettingsForTests.ConfigureSettings(config); - _container = new ServiceContainer(); - _container.ConfigureUmbracoCore(); + _container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + _container.ConfigureForUmbraco(); + _container.Register(_ => Mock.Of()); _container.Register(); _container.Register(_ => Mock.Of()); @@ -37,7 +37,7 @@ namespace Umbraco.Tests.IO _container.Register((f, x) => new MediaFileSystem(x, f.GetInstance(), f.GetInstance(), f.GetInstance())); _container.Register((f, x) => new NonConfiguredTypeFileSystem(x)); - + // make sure we start clean // because some tests will create corrupt or weird filesystems FileSystems.Reset(); diff --git a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs index edb9f2b97f..349804a432 100644 --- a/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs +++ b/src/Umbraco.Tests/Models/Mapping/AutoMapperTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using AutoMapper; using NUnit.Framework; @@ -9,7 +8,6 @@ using Umbraco.Core.Manifest; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -using LightInject; namespace Umbraco.Tests.Models.Mapping { diff --git a/src/Umbraco.Tests/Models/VariationTests.cs b/src/Umbraco.Tests/Models/VariationTests.cs index 194e3c5c43..0e4ec81a44 100644 --- a/src/Umbraco.Tests/Models/VariationTests.cs +++ b/src/Umbraco.Tests/Models/VariationTests.cs @@ -1,10 +1,8 @@ using System; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -28,8 +26,8 @@ namespace Umbraco.Tests.Models // need to be able to retrieve them all... Current.Reset(); - var container = Mock.Of(); - Current.Container = new LightInjectContainer(container); + var container = Mock.Of(); + Current.Container = container; var dataEditors = new DataEditorCollection(new IDataEditor[] { diff --git a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs index 27138bbccf..3576e3aa60 100644 --- a/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs +++ b/src/Umbraco.Tests/PropertyEditors/ImageCropperTest.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using LightInject; using Moq; using Newtonsoft.Json; using NUnit.Framework; @@ -9,7 +8,6 @@ using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; -using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; @@ -67,12 +65,13 @@ namespace Umbraco.Tests.PropertyEditors { try { - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); + container.RegisterCollectionBuilder(); - container.Register(f => Mock.Of()); - container.Register(f => Mock.Of()); + Current.Container.RegisterSingleton(f => Mock.Of()); + Current.Container.RegisterSingleton(f => Mock.Of()); var mediaFileSystem = new MediaFileSystem(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); var dataTypeService = new TestObjects.TestDataTypeService( diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index f7d09bd2c0..c7924f12a6 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -1,6 +1,5 @@ using System; using System.Threading; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -22,8 +21,9 @@ namespace Umbraco.Tests.PropertyEditors //normalize culture Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); + container.Register(_ => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GetDefaultUmbracoSettings()))); } diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index edc4face17..112dda9c17 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -172,8 +171,9 @@ namespace Umbraco.Tests.Published public void SimpleConverter3Test() { Current.Reset(); - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); + Current.Container.RegisterCollectionBuilder() .Append() diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs index 101c7827c3..0f7212a0b4 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentMoreTests.cs @@ -11,11 +11,10 @@ using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Core.Composing; using Current = Umbraco.Core.Composing.Current; -using LightInject; +using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Tests.Testing.Objects.Accessors; @@ -45,7 +44,7 @@ namespace Umbraco.Tests.PublishedContent Container.RegisterSingleton(f => new PublishedModelFactory(f.GetInstance().GetTypes())); } - protected override TypeLoader CreatePluginManager(IServiceFactory f) + protected override TypeLoader CreatePluginManager(IContainer f) { var pluginManager = base.CreatePluginManager(f); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs index b1fbc43f08..09665a4a7b 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTestBase.cs @@ -1,14 +1,11 @@ using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Tests.TestHelpers; -using LightInject; using Moq; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Services; using Umbraco.Web.PropertyEditors; namespace Umbraco.Tests.PublishedContent diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index fa120065bf..c52a3c73b0 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -9,7 +9,6 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Core.Composing; -using LightInject; using Moq; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -72,7 +71,7 @@ namespace Umbraco.Tests.PublishedContent ContentTypesCache.GetPublishedContentTypeByAlias = alias => type; } - protected override TypeLoader CreatePluginManager(IServiceFactory f) + protected override TypeLoader CreatePluginManager(IContainer f) { var pluginManager = base.CreatePluginManager(f); @@ -448,7 +447,7 @@ namespace Umbraco.Tests.PublishedContent public void FirstChildAsT() { var doc = GetNode(1046); // has child nodes - + var model = doc.FirstChild(x => true); // predicate Assert.IsNotNull(model); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs index 224b4a7934..239bfc7ad5 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs @@ -1,8 +1,8 @@ using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; -using LightInject; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs index 5080ab339d..dab0f15917 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs @@ -1,12 +1,10 @@ using Moq; using NUnit.Framework; -using LightInject; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Routing; using Umbraco.Core.Models; using Umbraco.Tests.Testing; using Current = Umbraco.Web.Composing.Current; -using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Tests.Routing { diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index fa4bb9b538..f4cf3f76a9 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Web.Mvc; using System.Web.Routing; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -14,13 +13,11 @@ using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; using Umbraco.Web.Models; using Umbraco.Web.Mvc; -using Umbraco.Web.Routing; using Umbraco.Web.WebApi; using Umbraco.Core.Strings; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.Testing; @@ -51,7 +48,7 @@ namespace Umbraco.Tests.Routing : base(umbracoApplication) { } - public override void Boot(ServiceContainer container) + public override void Boot(IContainer container) { // do it before anything else - this is the only place where it's possible var logger = Mock.Of(); diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 92c49b0950..504cbfb6ef 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -4,7 +4,6 @@ using System.Threading; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Configuration; using Umbraco.Tests.TestHelpers; using Umbraco.Web; using Umbraco.Core.IO; @@ -12,14 +11,10 @@ using Umbraco.Core.Logging; using Umbraco.Core.Sync; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; -// fixme - abstract container -using LightInject; - namespace Umbraco.Tests.Routing { [TestFixture] @@ -52,7 +47,7 @@ namespace Umbraco.Tests.Routing ); runtime.Level = RuntimeLevel.Run; - + //SettingsForTests.ReservedPaths = "~/umbraco,~/install/"; //SettingsForTests.ReservedUrls = "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd"; diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 770dead600..2c39f29b3b 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Web.Hosting; using Examine; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -13,7 +12,6 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; -using Umbraco.Examine; namespace Umbraco.Tests.Runtimes { @@ -83,7 +81,7 @@ namespace Umbraco.Tests.Runtimes : base(umbracoApplication) { } - public override void Compose(ServiceContainer container) + public override void Compose(IContainer container) { base.Compose(container); @@ -116,7 +114,7 @@ namespace Umbraco.Tests.Runtimes private MainDom _mainDom; - public override void Boot(ServiceContainer container) + public override void Boot(IContainer container) { base.Boot(container); _mainDom = container.GetInstance(); diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index b270fe8e22..0505072e5c 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -12,7 +11,6 @@ using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Services; @@ -31,13 +29,9 @@ namespace Umbraco.Tests.Scoping DoThing2 = null; DoThing3 = null; - var lightinjectContainer = new ServiceContainer(); - Current.Container = new LightInjectContainer(lightinjectContainer); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); - _testObjects = new TestObjects(lightinjectContainer); - - // fixme - move to container factory? - Current.Container.RegisterSingleton(f => (IServiceContainer)Current.Container.ConcreteContainer); + _testObjects = new TestObjects(container); Current.Container.RegisterSingleton(f => Current.Container); Current.Container.RegisterSingleton(factory => new FileSystems(factory.TryGetInstance())); diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 48bbdb1e22..875eabb13c 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Models; diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index ff1678fa3f..f88abb37a7 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -8,22 +7,17 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using LightInject; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Events; -using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Services.Implement; using Umbraco.Tests.Testing; -using Umbraco.Web.PropertyEditors; using System.Reflection; using Umbraco.Core.Cache; diff --git a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs index 2cbbfa6ebc..d925caa23f 100644 --- a/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs +++ b/src/Umbraco.Tests/Services/Importing/PackageImportTests.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Xml.Linq; @@ -11,7 +10,6 @@ using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.PropertyEditors; using Umbraco.Tests.Testing; -using LightInject; namespace Umbraco.Tests.Services.Importing { diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 36e5874e14..934d06840c 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -1,15 +1,12 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Composing; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index bc29139918..1078a49299 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -1,5 +1,4 @@ -using LightInject; -using Moq; +using Moq; using NPoco; using NUnit.Framework; using Umbraco.Core; @@ -7,7 +6,6 @@ using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; -using Umbraco.Core.Profiling; using Umbraco.Core.Composing; using Umbraco.Core.Persistence; @@ -34,8 +32,8 @@ namespace Umbraco.Tests.TestHelpers var sqlSyntax = new SqlCeSyntaxProvider(); - var container = new ServiceContainer(); - container.ConfigureUmbracoCore(); + var container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + container.ConfigureForUmbraco(); container.RegisterSingleton(factory => Mock.Of()); container.RegisterSingleton(factory => Mock.Of()); diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index 5eea6bcf72..421870c969 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -1,10 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading; -using LightInject; using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; @@ -86,12 +85,12 @@ namespace Umbraco.Tests.TestHelpers "; } - internal PublishedRouter CreatePublishedRouter(IServiceContainer container = null, ContentFinderCollection contentFinders = null) + internal PublishedRouter CreatePublishedRouter(IContainer container = null, ContentFinderCollection contentFinders = null) { return CreatePublishedRouter(TestObjects.GetUmbracoSettings().WebRouting, container, contentFinders); } - internal static PublishedRouter CreatePublishedRouter(IWebRoutingSection webRoutingSection, IServiceContainer container = null, ContentFinderCollection contentFinders = null) + internal static PublishedRouter CreatePublishedRouter(IWebRoutingSection webRoutingSection, IContainer container = null, ContentFinderCollection contentFinders = null) { return new PublishedRouter( webRoutingSection, diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index c9f74d689d..fb59ebee72 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net.Http; @@ -9,26 +8,19 @@ using System.Web.Http.Controllers; using System.Web.Http.Dispatcher; using System.Web.Security; using Moq; -using Semver; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Dictionary; -using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Security; using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Web.WebApi; -using LightInject; -using System.Globalization; using Umbraco.Core.Logging; using Umbraco.Tests.Testing.Objects.Accessors; diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 1cf39532a2..da96c40299 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -5,18 +5,16 @@ using System.Data.Common; using System.Linq; using System.Linq.Expressions; using System.Web; -using LightInject; using Moq; using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; using Umbraco.Web.PublishedCache; @@ -55,7 +53,7 @@ namespace Umbraco.Tests.TestHelpers /// Gets a mocked service context built with mocked services. /// /// A ServiceContext. - public ServiceContext GetServiceContextMock(IServiceFactory container = null) + public ServiceContext GetServiceContextMock(IContainer container = null) { return new ServiceContext( MockService(), @@ -83,7 +81,7 @@ namespace Umbraco.Tests.TestHelpers MockService()); } - private T MockService(IServiceFactory container = null) + private T MockService(IContainer container = null) where T : class { return container?.TryGetInstance() ?? new Mock().Object; diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index e091cc8d49..00a193b40a 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -1,9 +1,7 @@ using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; -using LightInject; using Moq; using NPoco; using Umbraco.Core; @@ -32,9 +30,9 @@ namespace Umbraco.Tests.TestHelpers /// internal partial class TestObjects { - private readonly IServiceContainer _container; + private readonly IContainer _container; - public TestObjects(IServiceContainer container) + public TestObjects(IContainer container) { _container = container; } @@ -85,7 +83,7 @@ namespace Umbraco.Tests.TestHelpers return new UmbracoDatabase(connection, sqlContext, logger); } - public void RegisterServices(IServiceContainer container) + public void RegisterServices(IContainer container) { } /// @@ -109,7 +107,7 @@ namespace Umbraco.Tests.TestHelpers IGlobalSettings globalSettings, IEventMessagesFactory eventMessagesFactory, IEnumerable urlSegmentProviders, - IServiceFactory container = null) + IContainer container = null) { if (scopeProvider == null) throw new ArgumentNullException(nameof(scopeProvider)); if (scopeAccessor == null) throw new ArgumentNullException(nameof(scopeAccessor)); @@ -220,13 +218,13 @@ namespace Umbraco.Tests.TestHelpers consentService); } - private Lazy GetLazyService(IServiceFactory container, Func ctor) + private Lazy GetLazyService(IContainer container, Func ctor) where T : class { return new Lazy(() => container?.TryGetInstance() ?? ctor(container)); } - private T GetRepo(IServiceFactory container) + private T GetRepo(IContainer container) where T : class, IRepository { return container?.TryGetInstance() ?? Mock.Of(); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 1b839a642e..f3029b3a35 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Reflection; using AutoMapper; using Examine; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -75,7 +74,7 @@ namespace Umbraco.Tests.Testing // test feature, and no test "base" class should be. only actual test feature classes // should be marked with that attribute. - protected ServiceContainer Container { get; private set; } + protected IContainer Container { get; private set; } protected UmbracoTestAttribute Options { get; private set; } @@ -114,8 +113,8 @@ namespace Umbraco.Tests.Testing // but hey, never know, better avoid garbage-in Reset(); - Container = new ServiceContainer(); - Container.ConfigureUmbracoCore(); + Container = Current.Container = new Core.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + Container.ConfigureForUmbraco(); TestObjects = new TestObjects(Container); @@ -238,12 +237,12 @@ namespace Umbraco.Tests.Testing }); } - protected virtual TypeLoader CreatePluginManager(IServiceFactory f) + protected virtual TypeLoader CreatePluginManager(IContainer f) { return CreateCommonPluginManager(f); } - private static TypeLoader CreateCommonPluginManager(IServiceFactory f) + private static TypeLoader CreateCommonPluginManager(IContainer f) { return new TypeLoader(f.GetInstance().RuntimeCache, f.GetInstance(), f.GetInstance(), false) { @@ -284,26 +283,9 @@ namespace Umbraco.Tests.Testing Container.RegisterSingleton(factory => umbracoSettings.Content); Container.RegisterSingleton(factory => umbracoSettings.Templates); Container.RegisterSingleton(factory => umbracoSettings.WebRouting); - - // fixme - The whole MediaFileSystem coupling thing seems broken. - Container.Register((factory, fileSystem) => new MediaFileSystem(fileSystem, factory.GetInstance(), factory.GetInstance(), factory.GetInstance())); - Container.RegisterConstructorDependency((factory, parameterInfo) => factory.GetInstance().MediaFileSystem); Container.RegisterSingleton(factory => ExamineManager.Instance); - // replace some stuff - Container.RegisterSingleton(factory => Mock.Of(), "ScriptFileSystem"); - Container.RegisterSingleton(factory => Mock.Of(), "PartialViewFileSystem"); - Container.RegisterSingleton(factory => Mock.Of(), "PartialViewMacroFileSystem"); - Container.RegisterSingleton(factory => Mock.Of(), "StylesheetFileSystem"); - - // need real file systems here as templates content is on-disk only - //Container.RegisterSingleton(factory => Mock.Of(), "MasterpageFileSystem"); - //Container.RegisterSingleton(factory => Mock.Of(), "ViewFileSystem"); - Container.RegisterSingleton(factory => new PhysicalFileSystem("Views", "/views"), "ViewFileSystem"); - Container.RegisterSingleton(factory => new PhysicalFileSystem("MasterPages", "/masterpages"), "MasterpageFileSystem"); - Container.RegisterSingleton(factory => new PhysicalFileSystem("Xslt", "/xslt"), "XsltFileSystem"); - // no factory (noop) Container.RegisterSingleton(); diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index 154b587a47..2597eab631 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -1,15 +1,9 @@ -using Moq; -using System.IO; -using LightInject; +using System.IO; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Profiling; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; -using Umbraco.Examine; namespace Umbraco.Tests.UmbracoExamine { diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index a4b210dbef..0ad3bff109 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -3,18 +3,13 @@ using System.Globalization; using System.Linq; using System.Web.Mvc; using System.Web.Routing; -using LightInject; using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Persistence; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.TestHelpers; diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index b2f18736a2..e60a4d9397 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -1,21 +1,17 @@ using System; -using System.Globalization; using System.Linq; using System.Web; -using LightInject; using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing.Objects.Accessors; using Umbraco.Web; using Umbraco.Web.PublishedCache; @@ -40,11 +36,11 @@ namespace Umbraco.Tests.Web var serviceContext = new ServiceContext(entityService: entityService.Object); // fixme - bad in a unit test - but Udi has a static ctor that wants it?! - var container = new Mock(); + var container = new Mock(); container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns( new TypeLoader(NullCacheProvider.Instance, SettingsForTests.GenerateMockGlobalSettings(), new ProfilingLogger(Mock.Of(), Mock.Of()))); container.Setup(x => x.GetInstance(typeof (ServiceContext))).Returns(serviceContext); - Current.Container = new LightInjectContainer(container.Object); + Current.Container = container.Object; Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor(); diff --git a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs index 480227f251..7a03fb3457 100644 --- a/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Web/Components/DatabaseServerRegistrarAndMessengerComponent.cs @@ -1,7 +1,6 @@ using System; using System.Threading; using Examine; -using LightInject; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Configuration; diff --git a/src/Umbraco.Web/LightInjectExtensions.cs b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs similarity index 65% rename from src/Umbraco.Web/LightInjectExtensions.cs rename to src/Umbraco.Web/Composing/Composers/ControllersComposer.cs index 580dc4117d..889ef195a5 100644 --- a/src/Umbraco.Web/LightInjectExtensions.cs +++ b/src/Umbraco.Web/Composing/Composers/ControllersComposer.cs @@ -1,49 +1,43 @@ using System.Reflection; using System.Web.Http.Controllers; using System.Web.Mvc; -using LightInject; -using Umbraco.Core; using Umbraco.Core.Composing; -namespace Umbraco.Web +namespace Umbraco.Web.Composing.Composers { - internal static class LightInjectExtensions + internal static class ControllersComposer { /// /// Registers all IControllers using the TypeLoader for scanning and caching found instances for the calling assembly /// - /// - /// - /// - public static void RegisterMvcControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly assembly) + public static IContainer ComposeMvcControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) { //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. container.RegisterControllers(typeLoader, assembly); + return container; } /// /// Registers all IHttpController using the TypeLoader for scanning and caching found instances for the calling assembly /// - /// - /// - /// - public static void RegisterApiControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly assembly) + public static IContainer ComposeApiControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) { //TODO: We've already scanned for UmbracoApiControllers and SurfaceControllers - should we scan again // for all controllers? Seems like we should just do this once and then filter. That said here we are // only scanning our own single assembly. Hrm. container.RegisterControllers(typeLoader, assembly); + return container; } - private static void RegisterControllers(this IServiceRegistry container, TypeLoader typeLoader, Assembly assembly) + private static void RegisterControllers(this IContainer container, TypeLoader typeLoader, Assembly assembly) { var types = typeLoader.GetTypes(specificAssemblies: new[] { assembly }); foreach (var type in types) - container.Register(type, new PerRequestLifeTime()); + container.Register(type, Lifetime.Request); } } } diff --git a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs index 265272cef2..9c701495fd 100644 --- a/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/InstallerComposer.cs @@ -1,4 +1,5 @@ -using LightInject; +using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Web.Install; using Umbraco.Web.Install.InstallSteps; using Umbraco.Web.Install.Models; @@ -7,10 +8,10 @@ namespace Umbraco.Web.Composing.Composers { public static class InstallerComposer { - public static IServiceRegistry ComposeInstaller(this IServiceRegistry registry) + public static IContainer ComposeInstaller(this IContainer container) { //register the installer steps in order - registry.RegisterOrdered(typeof(InstallSetupStep), + container.RegisterOrdered(typeof(InstallSetupStep), new[] { typeof(NewInstallStep), @@ -27,12 +28,12 @@ namespace Umbraco.Web.Composing.Composers //typeof(StarterKitCleanupStep), typeof(SetUmbracoVersionStep) - }, type => new PerScopeLifetime()); + }, Lifetime.Scope); - registry.Register(); - registry.Register(); + container.Register(); + container.Register(); - return registry; + return container; } } } diff --git a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs index 65fdd7fb72..b20b6348dd 100644 --- a/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs +++ b/src/Umbraco.Web/Composing/Composers/WebMappingProfilesComposer.cs @@ -1,4 +1,5 @@ -using LightInject; +using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Mapping; @@ -8,39 +9,39 @@ namespace Umbraco.Web.Composing.Composers { public static class WebMappingProfilesComposer { - public static IServiceRegistry ComposeWebMappingProfiles(this IServiceRegistry registry) + public static IContainer ComposeWebMappingProfiles(this IContainer container) { //register the profiles - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); - registry.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); + container.Register(); //register any resolvers, etc.. that the profiles use - registry.Register(); - registry.Register>(); - registry.Register>(); - registry.Register>(); - registry.Register>(); - registry.Register(); - registry.Register(); - registry.Register(); + container.Register(); + container.Register>(); + container.Register>(); + container.Register>(); + container.Register>(); + container.Register(); + container.Register(); + container.Register(); - return registry; + return container; } } } diff --git a/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs new file mode 100644 index 0000000000..1cc30be73f --- /dev/null +++ b/src/Umbraco.Web/Composing/LightInject/LightInjectContainer.cs @@ -0,0 +1,32 @@ +using System; +using System.Web.Http; +using LightInject; +using Umbraco.Core.Composing; + +namespace Umbraco.Web.Composing.LightInject +{ + /// + /// Implements with LightInject. + /// + public class LightInjectContainer : Core.Composing.LightInject.LightInjectContainer + { + /// + /// Initializes a new instance of the with a LightInject container. + /// + public LightInjectContainer(ServiceContainer container) + : base(container) + { } + + /// + public override void ConfigureForWeb() + { + // IoC setup for LightInject for MVC/WebApi + // see comments on MixedLightInjectScopeManagerProvider for explainations 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() + Container.ScopeManagerProvider = smp; // reverts - we will do it last (in WebRuntime) + Container.EnableWebApi(GlobalConfiguration.Configuration); + } + } +} diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index 332380009d..4e22907218 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -1,11 +1,8 @@ using System; -using LightInject; using Umbraco.Core.Composing; using Current = Umbraco.Web.Composing.Current; -using Umbraco.Core.Macros; using Umbraco.Web.Editors; using Umbraco.Web.HealthCheck; -using Umbraco.Web.Media; using Umbraco.Web.Mvc; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -32,7 +29,7 @@ namespace Umbraco.Core.Components /// internal static ActionCollectionBuilder Actions(this Composition composition) => composition.Container.GetInstance(); - + /// /// Gets the content finders collection builder. /// @@ -91,7 +88,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a last chance finder. - public static void SetContentLastChanceFinder(this Composition composition, Func factory) + public static void SetContentLastChanceFinder(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -132,7 +129,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a published snapshot service. - public static void SetPublishedSnapshotService(this Composition composition, Func factory) + public static void SetPublishedSnapshotService(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } @@ -163,7 +160,7 @@ namespace Umbraco.Core.Components /// /// The composition. /// A function creating a helper. - public static void SetSiteDomainHelper(this Composition composition, Func factory) + public static void SetSiteDomainHelper(this Composition composition, Func factory) { composition.Container.RegisterSingleton(factory); } diff --git a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs index 1d497d73e0..e526d3853a 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/NuCacheComponent.cs @@ -1,4 +1,5 @@ using Umbraco.Core.Components; +using Umbraco.Core; using Umbraco.Web.PublishedCache.NuCache.DataSource; namespace Umbraco.Web.PublishedCache.NuCache diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs index 496818ab28..ae3b442931 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlCacheComponent.cs @@ -6,7 +6,6 @@ using Umbraco.Core.Strings; using Umbraco.Core.Logging; using Umbraco.Core.Scoping; using Umbraco.Web.HealthCheck.Checks.DataIntegrity; -using LightInject; using Umbraco.Core.Configuration; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence.Repositories; diff --git a/src/Umbraco.Web/Runtime/WebRuntime.cs b/src/Umbraco.Web/Runtime/WebRuntime.cs index 0beacb1ee5..38c0c5ad50 100644 --- a/src/Umbraco.Web/Runtime/WebRuntime.cs +++ b/src/Umbraco.Web/Runtime/WebRuntime.cs @@ -1,6 +1,4 @@ -using System; -using System.Web; -using LightInject; +using System.Web; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; @@ -27,7 +25,7 @@ namespace Umbraco.Web.Runtime { } /// - public override void Boot(ServiceContainer container) + public override void Boot(IContainer container) { // create and start asap to profile boot var debug = GlobalSettings.DebugMode; @@ -46,13 +44,11 @@ namespace Umbraco.Web.Runtime base.Boot(container); // now (and only now) is the time to switch over to perWebRequest scopes - if (!(container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) - throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); - smp.EnablePerWebRequestScope(); + container.EnablePerWebRequestScope(); } /// - public override void Compose(ServiceContainer container) + public override void Compose(IContainer container) { base.Compose(container); diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs index 31deac6b68..29d40c0ce9 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComponent.cs @@ -14,7 +14,6 @@ using System.Web.Security; using ClientDependency.Core.CompositeFiles.Providers; using ClientDependency.Core.Config; using Examine; -using LightInject; using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; @@ -93,17 +92,17 @@ namespace Umbraco.Web.Runtime // register a per-request HttpContextBase object // is per-request so only one wrapper is created per request - composition.Container.Register(factory => new HttpContextWrapper(factory.GetInstance().HttpContext), new PerRequestLifeTime()); + composition.Container.RegisterSingleton(factory => new HttpContextWrapper(factory.GetInstance().HttpContext)); // register the published snapshot accessor - the "current" published snapshot is in the umbraco context composition.Container.RegisterSingleton(); // register a per-request UmbracoContext object // no real need to be per request but assuming it is faster - composition.Container.Register(factory => factory.GetInstance().UmbracoContext, new PerRequestLifeTime()); + composition.Container.RegisterSingleton(factory => factory.GetInstance().UmbracoContext); // register the umbraco helper - composition.Container.Register(new PerRequestLifeTime()); + composition.Container.RegisterSingleton(); // register distributed cache composition.Container.RegisterSingleton(f => new DistributedCache()); @@ -116,16 +115,10 @@ namespace Umbraco.Web.Runtime composition.Container.RegisterSingleton(factory => ExamineManager.Instance); - // IoC setup for LightInject for MVC/WebApi - // see comments on MixedLightInjectScopeManagerProvider for explainations of what we are doing here - if (!(composition.Container.ScopeManagerProvider is MixedLightInjectScopeManagerProvider smp)) - throw new Exception("Container.ScopeManagerProvider is not MixedLightInjectScopeManagerProvider."); - composition.Container.EnableMvc(); // does container.EnablePerWebRequestScope() - composition.Container.ScopeManagerProvider = smp; // reverts - we will do it last (in WebRuntime) - - composition.Container.RegisterMvcControllers(typeLoader, GetType().Assembly); - composition.Container.EnableWebApi(GlobalConfiguration.Configuration); - composition.Container.RegisterApiControllers(typeLoader, GetType().Assembly); + // configure the container for web + composition.Container.ConfigureForWeb(); + composition.Container.ComposeMvcControllers(typeLoader, GetType().Assembly); + composition.Container.ComposeApiControllers(typeLoader, GetType().Assembly); composition.Container.RegisterCollectionBuilder() .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?! @@ -200,7 +193,7 @@ namespace Umbraco.Web.Runtime composition.Container.Register(_ => UmbracoConfig.For.UmbracoSettings().WebRouting); // register preview SignalR hub - composition.Container.Register(_ => GlobalHost.ConnectionManager.GetHubContext(), new PerContainerLifetime()); + composition.Container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); // register properties fallback composition.Container.RegisterSingleton(); diff --git a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs index 07467d3bfa..20d7ec34cf 100644 --- a/src/Umbraco.Web/SignalR/PreviewHubComponent.cs +++ b/src/Umbraco.Web/SignalR/PreviewHubComponent.cs @@ -1,5 +1,4 @@ using System; -using LightInject; using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; @@ -14,7 +13,7 @@ namespace Umbraco.Web.SignalR public override void Compose(Composition composition) { base.Compose(composition); - composition.Container.Register(_ => GlobalHost.ConnectionManager.GetHubContext(), new PerContainerLifetime()); + composition.Container.RegisterSingleton(_ => GlobalHost.ConnectionManager.GetHubContext()); } // using a lazy arg here means that we won't create the hub until necessary diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 3ba65cd568..07850275d3 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -110,6 +110,7 @@ + @@ -165,7 +166,7 @@ - + diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 136f09f83d..bd790cdfb2 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -1,4 +1,5 @@ using Umbraco.Core; +using Umbraco.Core.Composing; using Umbraco.Web.Runtime; namespace Umbraco.Web @@ -12,5 +13,10 @@ namespace Umbraco.Web { return new WebRuntime(this); } + + protected override IContainer GetContainer() + { + return new Web.Composing.LightInject.LightInjectContainer(new LightInject.ServiceContainer()); + } } }