From a68b19f1ee2bbd58975a14a91533b5c7f5c9daf9 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 14 Jan 2019 14:28:19 +0100 Subject: [PATCH] More composition / filesystems fixes --- src/Umbraco.Core/Components/Composition.cs | 94 +++++++++++-------- .../Composing/CompositionExtensions.cs | 2 +- src/Umbraco.Core/Composing/IFactory.cs | 7 -- src/Umbraco.Core/Composing/IRegister.cs | 45 ++++----- .../LightInject/LightInjectContainer.cs | 65 +++++-------- .../MixedLightInjectScopeManagerProvider.cs | 3 + .../Composing/RegisterExtensions.cs | 6 +- src/Umbraco.Core/Configuration/Configs.cs | 2 +- .../Composing/ContainerConformingTests.cs | 8 +- 9 files changed, 115 insertions(+), 117 deletions(-) diff --git a/src/Umbraco.Core/Components/Composition.cs b/src/Umbraco.Core/Components/Composition.cs index 6cd8c8e5f0..6df86d793f 100644 --- a/src/Umbraco.Core/Components/Composition.cs +++ b/src/Umbraco.Core/Components/Composition.cs @@ -81,29 +81,34 @@ namespace Umbraco.Core.Components public void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient) => _register.Register(serviceType, implementingType, lifetime); - /// - public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) - where TService : class - => _register.RegisterFor(implementingType, lifetime); - /// public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class => _register.Register(factory, lifetime); + /// + public void Register(Type serviceType, object instance) + => _register.Register(serviceType, instance); + + /// + public void RegisterFor(Lifetime lifetime = Lifetime.Transient) + where TService : class + => _register.RegisterFor(lifetime); + + /// + public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) + where TService : class + => _register.RegisterFor(implementingType, lifetime); + /// public void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class => _register.RegisterFor(factory, lifetime); /// - public void RegisterInstance(Type serviceType, object instance) - => _register.RegisterInstance(serviceType, instance); - - /// - public void RegisterInstanceFor(TService instance) + public void RegisterFor(TService instance) where TService : class - => _register.RegisterInstanceFor(instance); + => _register.RegisterFor(instance); /// public void RegisterAuto(Type serviceBaseType) @@ -154,37 +159,21 @@ namespace Umbraco.Core.Components => serviceType.FullName + "::" + targetType.FullName; /// - /// Registers a unique service. + /// Registers a unique service as its own implementation. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Type serviceType) + => _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, Lifetime.Singleton); + + /// + /// Registers a unique service with an implementation type. /// /// Unique services have one single implementation, and a Singleton lifetime. public void RegisterUnique(Type serviceType, Type implementingType) => _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, implementingType, Lifetime.Singleton); /// - /// Registers a unique service, for a target. - /// - /// Unique services have one single implementation, and a Singleton lifetime. - public void RegisterUniqueFor(Type implementingType) - where TService : class - => _uniques[GetUniqueName()] = register => register.RegisterFor(implementingType, Lifetime.Singleton); - - /// - /// Registers a unique service. - /// - /// Unique services have one single implementation, and a Singleton lifetime. - public void RegisterUniqueInstance(Type serviceType, object instance) - => _uniques[GetUniqueName(serviceType)] = register => register.RegisterInstance(serviceType, instance); - - /// - /// Registers a unique service, for a target. - /// - /// Unique services have one single implementation, and a Singleton lifetime. - public void RegisterUniqueInstanceFor(TService instance) - where TService : class - => _uniques[GetUniqueName()] = register => register.RegisterInstanceFor(instance); - - /// - /// Registers a unique service. + /// Registers a unique service with an implementation factory. /// /// Unique services have one single implementation, and a Singleton lifetime. public void RegisterUnique(Func factory) @@ -192,13 +181,44 @@ namespace Umbraco.Core.Components => _uniques[GetUniqueName()] = register => register.Register(factory, Lifetime.Singleton); /// - /// Registers a unique service, for a target. + /// Registers a unique service with an implementing instance. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUnique(Type serviceType, object instance) + => _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, instance); + + /// + /// Registers a unique service for a target, as its own implementation. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueFor() + where TService : class + => _uniques[GetUniqueName()] = register => register.RegisterFor(Lifetime.Singleton); + + /// + /// Registers a unique service for a target, with an implementing type. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueFor(Type implementingType) + where TService : class + => _uniques[GetUniqueName()] = register => register.RegisterFor(implementingType, Lifetime.Singleton); + + /// + /// Registers a unique service for a target, with an implementation factory. /// /// Unique services have one single implementation, and a Singleton lifetime. public void RegisterUniqueFor(Func factory) where TService : class => _uniques[GetUniqueName()] = register => register.RegisterFor(factory, Lifetime.Singleton); + /// + /// Registers a unique service for a target, with an implementing instance. + /// + /// Unique services have one single implementation, and a Singleton lifetime. + public void RegisterUniqueFor(TService instance) + where TService : class + => _uniques[GetUniqueName()] = register => register.RegisterFor(instance); + #endregion #region Collection Builders diff --git a/src/Umbraco.Core/Composing/CompositionExtensions.cs b/src/Umbraco.Core/Composing/CompositionExtensions.cs index ac9a5d6409..2307d757c9 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions.cs @@ -62,7 +62,7 @@ namespace Umbraco.Core.Composing /// Registers a unique service with an implementing instance. /// public static void RegisterUnique(this Composition composition, TService instance) - => composition.RegisterUniqueInstance(typeof(TService), instance); + => composition.RegisterUnique(typeof(TService), instance); #endregion } diff --git a/src/Umbraco.Core/Composing/IFactory.cs b/src/Umbraco.Core/Composing/IFactory.cs index 20fbe33737..768b9207a3 100644 --- a/src/Umbraco.Core/Composing/IFactory.cs +++ b/src/Umbraco.Core/Composing/IFactory.cs @@ -3,13 +3,6 @@ using System.Collections.Generic; namespace Umbraco.Core.Composing { - // Implementing: - // - // The factory - // - always picks the constructor with the most parameters - // - supports Lazy parameters (and prefers them over non-Lazy) in constructors - // - what happens with 'releasing' is unclear - /// /// Defines a service factory for Umbraco. /// diff --git a/src/Umbraco.Core/Composing/IRegister.cs b/src/Umbraco.Core/Composing/IRegister.cs index d145df8790..3e6aed67ee 100644 --- a/src/Umbraco.Core/Composing/IRegister.cs +++ b/src/Umbraco.Core/Composing/IRegister.cs @@ -2,17 +2,6 @@ namespace Umbraco.Core.Composing { - // Implementing: - // - // The register - // - supports registering a service, even after some instances of other services have been created - // - supports re-registering a service, as long as no instance of that service has been created - // - throws when re-registering a service, and an instance of that service has been created - // - // - registers only one implementation of a nameless service, re-registering replaces the previous - // registration - names are required to register multiple implementations - and getting an - // IEnumerable of the service, nameless, returns them all - /// /// Defines a service register for Umbraco. /// @@ -33,12 +22,6 @@ namespace Umbraco.Core.Composing /// void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient); - /// - /// Registers a service with an implementation type, for a target. - /// - void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) - where TService : class; - /// /// Registers a service with an implementation factory. /// @@ -46,20 +29,32 @@ namespace Umbraco.Core.Composing where TService : class; /// - /// Registers a service with an implementation factory, for a target. + /// Registers a service with an implementing instance. + /// + void Register(Type serviceType, object instance); + + /// + /// Registers a service for a target, as its own implementation. + /// + void RegisterFor(Lifetime lifetime = Lifetime.Transient) + where TService : class; + + /// + /// Registers a service for a target, with an implementation type. + /// + void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) + where TService : class; + + /// + /// Registers a service for a target, with an implementation factory. /// void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class; /// - /// Registers a service with an implementing instance. + /// Registers a service for a target, with an implementing instance. /// - void RegisterInstance(Type serviceType, object instance); - - /// - /// Registers a service with an implementing instance, for a target. - /// - void RegisterInstanceFor(TService instance) + void RegisterFor(TService instance) where TService : class; /// diff --git a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs index 4ccc0ba838..d8a554ee8c 100644 --- a/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs +++ b/src/Umbraco.Core/Composing/LightInject/LightInjectContainer.cs @@ -145,9 +145,7 @@ namespace Umbraco.Core.Composing.LightInject /// public void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient) - { - Container.Register(serviceType, GetLifetime(lifetime)); - } + => Container.Register(serviceType, GetLifetime(lifetime)); /// public void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient) @@ -167,13 +165,6 @@ namespace Umbraco.Core.Composing.LightInject } } - /// - public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) - where TService : class - { - Container.Register(typeof(TService), implementingType, GetTargetedServiceName(), GetLifetime(lifetime)); - } - /// public void Register(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class @@ -181,13 +172,36 @@ namespace Umbraco.Core.Composing.LightInject Container.Register(f => factory(this), GetLifetime(lifetime)); } + /// + public void Register(Type serviceType, object instance) + => Container.RegisterInstance(serviceType, instance); + + /// + public void RegisterFor(Lifetime lifetime = Lifetime.Transient) + where TService : class + => RegisterFor(typeof(TService), lifetime); + + /// + public void RegisterFor(Type implementingType, Lifetime lifetime = Lifetime.Transient) + where TService : class + { + // note that there can only be one implementation or instance registered "for" a service + Container.Register(typeof(TService), implementingType, GetTargetedServiceName(), GetLifetime(lifetime)); + } + /// public void RegisterFor(Func factory, Lifetime lifetime = Lifetime.Transient) where TService : class { + // note that there can only be one implementation or instance registered "for" a service Container.Register(f => factory(this), GetTargetedServiceName(), GetLifetime(lifetime)); } + /// + public void RegisterFor(TService instance) + where TService : class + => Container.RegisterInstance(typeof(TService), instance, GetTargetedServiceName()); + private ILifetime GetLifetime(Lifetime lifetime) { switch (lifetime) @@ -205,15 +219,6 @@ namespace Umbraco.Core.Composing.LightInject } } - /// - public void RegisterInstance(Type serviceType, object instance) - => Container.RegisterInstance(serviceType, instance); - - /// - public void RegisterInstanceFor(TService instance) - where TService : class - => Container.RegisterInstance(typeof(TService), instance, GetTargetedServiceName()); - /// public void RegisterAuto(Type serviceBaseType) { @@ -226,17 +231,6 @@ namespace Umbraco.Core.Composing.LightInject }, null); } - // was the Light-Inject specific way of dealing with args, but we've replaced it with our own - // beware! does NOT work on singletons, see https://github.com/seesharper/LightInject/issues/294 - // - ///// - //public void RegisterConstructorDependency(Func factory) - // => Container.RegisterConstructorDependency((f, x) => factory(this, x)); - // - ///// - //public void RegisterConstructorDependency(Func factory) - // => Container.RegisterConstructorDependency((f, x, a) => factory(this, x, a)); - #endregion #region Control @@ -259,21 +253,14 @@ namespace Umbraco.Core.Composing.LightInject 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 + // nothing - we don't want LightInject to scan } public void Scan(Assembly assembly, IServiceRegistry serviceRegistry) { - // nothing - we *could* scan non-Umbraco assemblies, though + // nothing - we don't want LightInject to scan } } diff --git a/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs b/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs index 470079c6c0..897c58dd43 100644 --- a/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs +++ b/src/Umbraco.Core/Composing/LightInject/MixedLightInjectScopeManagerProvider.cs @@ -13,6 +13,9 @@ namespace Umbraco.Core.Composing.LightInject // of PerWebRequestScopeManagerProvider - but all delegates see is the mixed one - and therefore // they can transition without issues. // + // The PerWebRequestScopeManager maintains the scope in HttpContext and LightInject registers a + // module (PreApplicationStartMethod) which disposes it on EndRequest + // // the mixed provider is installed in container.ConfigureUmbracoCore() and then, // when doing eg container.EnableMvc() or anything that does container.EnablePerWebRequestScope() // we need to take great care to preserve the mixed scope manager provider! diff --git a/src/Umbraco.Core/Composing/RegisterExtensions.cs b/src/Umbraco.Core/Composing/RegisterExtensions.cs index 9afa41e4b3..d1eacc0c0f 100644 --- a/src/Umbraco.Core/Composing/RegisterExtensions.cs +++ b/src/Umbraco.Core/Composing/RegisterExtensions.cs @@ -14,7 +14,7 @@ /// /// Registers a service with an implementation type, for a target. /// - public static void RegisterFor(this IRegister register, Lifetime lifetime = Lifetime.Transient) + public static void RegisterFor(this IRegister register, Lifetime lifetime = Lifetime.Transient) where TService : class => register.RegisterFor(typeof(TImplementing), lifetime); @@ -28,9 +28,9 @@ /// /// Registers a service with an implementing instance. /// - public static void RegisterInstance(this IRegister register, TService instance) + public static void Register(this IRegister register, TService instance) where TService : class - => register.RegisterInstance(typeof(TService), instance); + => register.Register(typeof(TService), instance); /// /// Registers a base type for auto-registration. diff --git a/src/Umbraco.Core/Configuration/Configs.cs b/src/Umbraco.Core/Configuration/Configs.cs index 3dbbe5d4ff..51e1a327a0 100644 --- a/src/Umbraco.Core/Configuration/Configs.cs +++ b/src/Umbraco.Core/Configuration/Configs.cs @@ -100,7 +100,7 @@ namespace Umbraco.Core.Configuration if (_registerings == null) throw new InvalidOperationException("Configurations have already been registered."); - register.RegisterInstance(this); + register.Register(this); foreach (var registering in _registerings.Values) registering(register); diff --git a/src/Umbraco.Tests/Composing/ContainerConformingTests.cs b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs index 9585c98cb2..21ea961636 100644 --- a/src/Umbraco.Tests/Composing/ContainerConformingTests.cs +++ b/src/Umbraco.Tests/Composing/ContainerConformingTests.cs @@ -194,8 +194,8 @@ namespace Umbraco.Tests.Composing var register = GetRegister(); // define two instances - register.RegisterInstance(typeof(Thing1), new Thing1()); - register.RegisterInstance(typeof(Thing1), new Thing2()); + register.Register(typeof(Thing1), new Thing1()); + register.Register(typeof(Thing1), new Thing2()); var factory = register.CreateFactory(); @@ -212,8 +212,8 @@ namespace Umbraco.Tests.Composing var register = GetRegister(); // define two instances - register.RegisterInstance(typeof(IThing), new Thing1()); - register.RegisterInstance(typeof(IThing), new Thing2()); + register.Register(typeof(IThing), new Thing1()); + register.Register(typeof(IThing), new Thing2()); var factory = register.CreateFactory();