Merge pull request #4059 from umbraco/temp8-fs

Cleanup Filesystems registrations
This commit is contained in:
Warren Buckley
2019-01-14 14:56:16 +00:00
committed by GitHub
20 changed files with 291 additions and 162 deletions

View File

@@ -17,7 +17,7 @@ namespace Umbraco.Core.Components
public class Composition : IRegister
{
private readonly Dictionary<Type, ICollectionBuilder> _builders = new Dictionary<Type, ICollectionBuilder>();
private readonly Dictionary<Type, Unique> _uniques = new Dictionary<Type, Unique>();
private readonly Dictionary<string, Action<IRegister>> _uniques = new Dictionary<string, Action<IRegister>>();
private readonly IRegister _register;
/// <summary>
@@ -83,11 +83,32 @@ namespace Umbraco.Core.Components
/// <inheritdoc />
public void Register<TService>(Func<IFactory, TService> factory, Lifetime lifetime = Lifetime.Transient)
where TService : class
=> _register.Register(factory, lifetime);
/// <inheritdoc />
public void RegisterInstance(Type serviceType, object instance)
=> _register.RegisterInstance(serviceType, instance);
public void Register(Type serviceType, object instance)
=> _register.Register(serviceType, instance);
/// <inheritdoc />
public void RegisterFor<TService, TTarget>(Lifetime lifetime = Lifetime.Transient)
where TService : class
=> _register.RegisterFor<TService, TTarget>(lifetime);
/// <inheritdoc />
public void RegisterFor<TService, TTarget>(Type implementingType, Lifetime lifetime = Lifetime.Transient)
where TService : class
=> _register.RegisterFor<TService, TTarget>(implementingType, lifetime);
/// <inheritdoc />
public void RegisterFor<TService, TTarget>(Func<IFactory, TService> factory, Lifetime lifetime = Lifetime.Transient)
where TService : class
=> _register.RegisterFor<TService, TTarget>(factory, lifetime);
/// <inheritdoc />
public void RegisterFor<TService, TTarget>(TService instance)
where TService : class
=> _register.RegisterFor<TService, TTarget>(instance);
/// <inheritdoc />
public void RegisterAuto(Type serviceBaseType)
@@ -104,10 +125,12 @@ namespace Umbraco.Core.Components
onCreating();
foreach (var unique in _uniques.Values)
unique.RegisterWith(_register);
unique(_register);
_uniques.Clear(); // no point keep them around
foreach (var builder in _builders.Values)
builder.RegisterWith(_register);
_builders.Clear(); // no point keep them around
Configs.RegisterWith(_register);
@@ -123,74 +146,78 @@ namespace Umbraco.Core.Components
#region Unique
private string GetUniqueName<TService>()
=> GetUniqueName(typeof(TService));
private string GetUniqueName(Type serviceType)
=> serviceType.FullName;
private string GetUniqueName<TService, TTarget>()
=> GetUniqueName(typeof(TService), typeof(TTarget));
private string GetUniqueName(Type serviceType, Type targetType)
=> serviceType.FullName + "::" + targetType.FullName;
/// <summary>
/// Registers a unique service.
/// Registers a unique service as its own implementation.
/// </summary>
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
public void RegisterUnique(Type serviceType)
=> _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, Lifetime.Singleton);
/// <summary>
/// Registers a unique service with an implementation type.
/// </summary>
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
public void RegisterUnique(Type serviceType, Type implementingType)
=> _uniques[serviceType] = new Unique(serviceType, implementingType);
=> _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, implementingType, Lifetime.Singleton);
/// <summary>
/// Registers a unique service.
/// </summary>
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
public void RegisterUnique(Type serviceType, object instance)
=> _uniques[serviceType] = new Unique(serviceType, instance);
/// <summary>
/// Registers a unique service.
/// Registers a unique service with an implementation factory.
/// </summary>
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
public void RegisterUnique<TService>(Func<IFactory, TService> factory)
=> _uniques[typeof(TService)] = new Unique<TService>(factory);
where TService : class
=> _uniques[GetUniqueName<TService>()] = register => register.Register<TService>(factory, Lifetime.Singleton);
private class Unique
{
private readonly Type _serviceType;
private readonly Type _implementingType;
private readonly object _instance;
/// <summary>
/// Registers a unique service with an implementing instance.
/// </summary>
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
public void RegisterUnique(Type serviceType, object instance)
=> _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, instance);
protected Unique(Type serviceType)
{
_serviceType = serviceType;
}
/// <summary>
/// Registers a unique service for a target, as its own implementation.
/// </summary>
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
public void RegisterUniqueFor<TService, TTarget>()
where TService : class
=> _uniques[GetUniqueName<TService, TTarget>()] = register => register.RegisterFor<TService, TTarget>(Lifetime.Singleton);
public Unique(Type serviceType, Type implementingType)
: this(serviceType)
{
_implementingType = implementingType;
}
/// <summary>
/// Registers a unique service for a target, with an implementing type.
/// </summary>
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
public void RegisterUniqueFor<TService, TTarget>(Type implementingType)
where TService : class
=> _uniques[GetUniqueName<TService, TTarget>()] = register => register.RegisterFor<TService, TTarget>(implementingType, Lifetime.Singleton);
public Unique(Type serviceType, object instance)
: this(serviceType)
{
_instance = instance;
}
/// <summary>
/// Registers a unique service for a target, with an implementation factory.
/// </summary>
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
public void RegisterUniqueFor<TService, TTarget>(Func<IFactory, TService> factory)
where TService : class
=> _uniques[GetUniqueName<TService, TTarget>()] = register => register.RegisterFor<TService, TTarget>(factory, Lifetime.Singleton);
public virtual void RegisterWith(IRegister register)
{
if (_implementingType != null)
register.Register(_serviceType, _implementingType, Lifetime.Singleton);
else if (_instance != null)
register.RegisterInstance(_serviceType, _instance);
}
}
private class Unique<TService> : Unique
{
private readonly Func<IFactory, TService> _factory;
public Unique(Func<IFactory, TService> factory)
: base(typeof(TService))
{
_factory = factory;
}
public override void RegisterWith(IRegister register)
{
register.Register(_factory, Lifetime.Singleton);
}
}
/// <summary>
/// Registers a unique service for a target, with an implementing instance.
/// </summary>
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
public void RegisterUniqueFor<TService, TTarget>(TService instance)
where TService : class
=> _uniques[GetUniqueName<TService, TTarget>()] = register => register.RegisterFor<TService, TTarget>(instance);
#endregion

View File

@@ -26,15 +26,16 @@ namespace Umbraco.Core.Components
/// <typeparam name="TFileSystem">The type of the filesystem.</typeparam>
/// <typeparam name="TImplementing">The implementing type.</typeparam>
/// <param name="composition">The composition.</param>
/// <param name="supportingFileSystemFactory">A factory method creating the supporting filesystem.</param>
/// <returns>The register.</returns>
public static void RegisterFileSystem<TFileSystem, TImplementing>(this Composition composition, Func<IFactory, IFileSystem> supportingFileSystemFactory)
public static void RegisterFileSystem<TFileSystem, TImplementing>(this Composition composition)
where TImplementing : FileSystemWrapper, TFileSystem
where TFileSystem : class
{
composition.RegisterUnique<TFileSystem>(factory =>
{
var fileSystems = factory.GetInstance<FileSystems>();
return fileSystems.GetFileSystem<TImplementing>(supportingFileSystemFactory(factory));
var supporting = factory.GetInstance<SupportingFileSystems>();
return fileSystems.GetFileSystem<TImplementing>(supporting.For<TFileSystem>());
});
}
@@ -43,15 +44,15 @@ namespace Umbraco.Core.Components
/// </summary>
/// <typeparam name="TFileSystem">The type of the filesystem.</typeparam>
/// <param name="composition">The composition.</param>
/// <param name="supportingFileSystemFactory">A factory method creating the supporting filesystem.</param>
/// <returns>The register.</returns>
public static void RegisterFileSystem<TFileSystem>(this Composition composition, Func<IFactory, IFileSystem> supportingFileSystemFactory)
public static void RegisterFileSystem<TFileSystem>(this Composition composition)
where TFileSystem : FileSystemWrapper
{
composition.RegisterUnique(factory =>
{
var fileSystems = factory.GetInstance<FileSystems>();
return fileSystems.GetFileSystem<TFileSystem>(supportingFileSystemFactory(factory));
var supporting = factory.GetInstance<SupportingFileSystems>();
return fileSystems.GetFileSystem<TFileSystem>(supporting.For<TFileSystem>());
});
}
@@ -280,6 +281,22 @@ namespace Umbraco.Core.Components
composition.RegisterUnique(_ => helper);
}
/// <summary>
/// Sets the underlying media filesystem.
/// </summary>
/// <param name="composition">A composition.</param>
/// <param name="filesystemFactory">A filesystem factory.</param>
public static void SetMediaFileSystem(this Composition composition, Func<IFactory, IFileSystem> filesystemFactory)
=> composition.RegisterUniqueFor<IFileSystem, IMediaFileSystem>(filesystemFactory);
/// <summary>
/// Sets the underlying media filesystem.
/// </summary>
/// <param name="composition">A composition.</param>
/// <param name="filesystemFactory">A filesystem factory.</param>
public static void SetMediaFileSystem(this Composition composition, Func<IFileSystem> filesystemFactory)
=> composition.RegisterUniqueFor<IFileSystem, IMediaFileSystem>(_ => filesystemFactory());
#endregion
}
}

View File

@@ -12,7 +12,7 @@ namespace Umbraco.Core.Composing
/// <typeparam name="TItem">The type of the items.</typeparam>
public abstract class CollectionBuilderBase<TBuilder, TCollection, TItem> : ICollectionBuilder<TCollection, TItem>
where TBuilder: CollectionBuilderBase<TBuilder, TCollection, TItem>
where TCollection : IBuilderCollection<TItem>
where TCollection : class, IBuilderCollection<TItem>
{
private readonly List<Type> _types = new List<Type>();
private readonly object _locker = new object();

View File

@@ -12,10 +12,9 @@ namespace Umbraco.Core.Composing.Composers
*
* Create a component and use it to modify the composition by adding something like:
*
* composition.Container.RegisterFileSystem<IMediaFileSystem, MediaFileSystem>(
* factory => new PhysicalFileSystem("~/somewhere"));
* composition.RegisterUniqueFor<IFileSystem, IMediaFileSystem>(...);
*
* return whatever supporting filesystem you like.
* and register whatever supporting filesystem you like.
*
*
* HOW TO IMPLEMENT MY OWN FILESYSTEM
@@ -30,12 +29,15 @@ namespace Umbraco.Core.Composing.Composers
* { }
* }
*
* The ctor can have more parameters that will be resolved by the container.
* The ctor can have more parameters, that will be resolved by the container.
*
* Register your filesystem, in a component:
*
* composition.Container.RegisterFileSystem<MyFileSystem>(
* factory => new PhysicalFileSystem("~/my"));
* composition.RegisterFileSystem<MyFileSystem>();
*
* Register the underlying filesystem:
*
* composition.RegisterUniqueFor<IFileSystem, MyFileSystem>(...);
*
* And that's it, you can inject MyFileSystem wherever it's needed.
*
@@ -48,8 +50,8 @@ namespace Umbraco.Core.Composing.Composers
* Make the class implement the interface, then
* register your filesystem, in a component:
*
* composition.Container.RegisterFileSystem<IMyFileSystem, MyFileSystem>(
* factory => new PhysicalFileSystem("~/my"));
* composition.RegisterFileSystem<IMyFileSystem, MyFileSystem>();
* composition.RegisterUniqueFor<IFileSystem, IMyFileSystem>(...);
*
* And that's it, you can inject IMyFileSystem wherever it's needed.
*
@@ -79,9 +81,16 @@ namespace Umbraco.Core.Composing.Composers
// register the scheme for media paths
composition.RegisterUnique<IMediaPathScheme, TwoGuidsMediaPathScheme>();
// register the IMediaFileSystem implementation with a supporting filesystem
composition.RegisterFileSystem<IMediaFileSystem, MediaFileSystem>(
factory => new PhysicalFileSystem("~/media"));
// register the IMediaFileSystem implementation
composition.RegisterFileSystem<IMediaFileSystem, MediaFileSystem>();
// register the supporting filesystems provider
composition.Register(factory => new SupportingFileSystems(factory), Lifetime.Singleton);
// register the IFileSystem supporting the IMediaFileSystem
// THIS IS THE ONLY THING THAT NEEDS TO CHANGE, IN ORDER TO REPLACE THE UNDERLYING FILESYSTEM
// and, SupportingFileSystem.For<IMediaFileSystem>() returns the underlying filesystem
composition.SetMediaFileSystem(() => new PhysicalFileSystem("~/media"));
return composition;
}

View File

@@ -51,6 +51,13 @@ namespace Umbraco.Core.Composing
public static void RegisterUnique<TService, TImplementing>(this Composition composition)
=> composition.RegisterUnique(typeof(TService), typeof(TImplementing));
/// <summary>
/// Registers a unique service with an implementation type, for a target.
/// </summary>
public static void RegisterUniqueFor<TService, TTarget, TImplementing>(this Composition composition)
where TService : class
=> composition.RegisterUniqueFor<TService, TTarget>(typeof(TImplementing));
/// <summary>
/// Registers a unique service with an implementing instance.
/// </summary>

View File

@@ -17,6 +17,7 @@ namespace Umbraco.Core.Composing
/// <returns>An instance of the specified type.</returns>
/// <remarks>Throws an exception if the factory failed to get an instance of the specified type.</remarks>
public static T GetInstance<T>(this IFactory factory)
where T : class
=> (T)factory.GetInstance(typeof(T));
/// <summary>
@@ -28,6 +29,7 @@ namespace Umbraco.Core.Composing
/// of the specified type. Throws an exception if the factory does know how
/// to get an instance of the specified type, but failed to do so.</remarks>
public static T TryGetInstance<T>(this IFactory factory)
where T : class
=> (T)factory.TryGetInstance(typeof(T));
/// <summary>
@@ -42,6 +44,7 @@ namespace Umbraco.Core.Composing
/// <para>The arguments are used as dependencies by the factory.</para>
/// </remarks>
public static T CreateInstance<T>(this IFactory factory, params object[] args)
where T : class
=> (T)factory.CreateInstance(typeof(T), args);
/// <summary>

View File

@@ -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
/// <summary>
/// Defines a service factory for Umbraco.
/// </summary>
@@ -28,6 +21,15 @@ namespace Umbraco.Core.Composing
/// <remarks>Throws an exception if the container failed to get an instance of the specified type.</remarks>
object GetInstance(Type type);
/// <summary>
/// Gets a targeted instance of a service.
/// </summary>
/// <typeparam name="TService">The type of the service.</typeparam>
/// <typeparam name="TTarget">The type of the target.</typeparam>
/// <returns>The instance of the specified type for the specified target.</returns>
/// <remarks>Throws an exception if the container failed to get an instance of the specified type.</remarks>
TService GetInstanceFor<TService, TTarget>();
/// <summary>
/// Tries to get an instance of a service.
/// </summary>
@@ -48,7 +50,8 @@ namespace Umbraco.Core.Composing
/// Gets all instances of a service.
/// </summary>
/// <typeparam name="TService">The type of the service.</typeparam>
IEnumerable<TService> GetAllInstances<TService>();
IEnumerable<TService> GetAllInstances<TService>()
where TService : class;
/// <summary>
/// Releases an instance.

View File

@@ -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
/// <summary>
/// Defines a service register for Umbraco.
/// </summary>
@@ -36,12 +25,53 @@ namespace Umbraco.Core.Composing
/// <summary>
/// Registers a service with an implementation factory.
/// </summary>
void Register<TService>(Func<IFactory, TService> factory, Lifetime lifetime = Lifetime.Transient);
void Register<TService>(Func<IFactory, TService> factory, Lifetime lifetime = Lifetime.Transient)
where TService : class;
/// <summary>
/// Registers a service with an implementing instance.
/// </summary>
void RegisterInstance(Type serviceType, object instance);
void Register(Type serviceType, object instance);
/// <summary>
/// Registers a service for a target, as its own implementation.
/// </summary>
/// <remarks>
/// There can only be one implementation or instanced registered for a service and target;
/// what happens if many are registered is not specified.
/// </remarks>
void RegisterFor<TService, TTarget>(Lifetime lifetime = Lifetime.Transient)
where TService : class;
/// <summary>
/// Registers a service for a target, with an implementation type.
/// </summary>
/// <remarks>
/// There can only be one implementation or instanced registered for a service and target;
/// what happens if many are registered is not specified.
/// </remarks>
void RegisterFor<TService, TTarget>(Type implementingType, Lifetime lifetime = Lifetime.Transient)
where TService : class;
/// <summary>
/// Registers a service for a target, with an implementation factory.
/// </summary>
/// <remarks>
/// There can only be one implementation or instanced registered for a service and target;
/// what happens if many are registered is not specified.
/// </remarks>
void RegisterFor<TService, TTarget>(Func<IFactory, TService> factory, Lifetime lifetime = Lifetime.Transient)
where TService : class;
/// <summary>
/// Registers a service for a target, with an implementing instance.
/// </summary>
/// <remarks>
/// There can only be one implementation or instanced registered for a service and target;
/// what happens if many are registered is not specified.
/// </remarks>
void RegisterFor<TService, TTarget>(TService instance)
where TService : class;
/// <summary>
/// Registers a base type for auto-registration.

View File

@@ -12,7 +12,7 @@ namespace Umbraco.Core.Composing
/// <typeparam name="TItem">The type of the items.</typeparam>
public abstract class LazyCollectionBuilderBase<TBuilder, TCollection, TItem> : CollectionBuilderBase<TBuilder, TCollection, TItem>
where TBuilder : LazyCollectionBuilderBase<TBuilder, TCollection, TItem>
where TCollection : IBuilderCollection<TItem>
where TCollection : class, IBuilderCollection<TItem>
{
private readonly List<Func<IEnumerable<Type>>> _producers = new List<Func<IEnumerable<Type>>>();
private readonly List<Type> _excluded = new List<Type>();

View File

@@ -102,18 +102,25 @@ namespace Umbraco.Core.Composing.LightInject
/// <inheritdoc />
public IFactory CreateFactory() => this;
private static string GetTargetedServiceName<TTarget>() => "TARGET:" + typeof(TTarget).FullName;
#region Factory
/// <inheritdoc />
public object GetInstance(Type type)
=> Container.GetInstance(type);
/// <inheritdoc />
public TService GetInstanceFor<TService, TTarget>()
=> Container.GetInstance<TService>(GetTargetedServiceName<TTarget>());
/// <inheritdoc />
public object TryGetInstance(Type type)
=> Container.TryGetInstance(type);
/// <inheritdoc />
public IEnumerable<T> GetAllInstances<T>()
where T : class
=> Container.GetAllInstances<T>();
/// <inheritdoc />
@@ -138,21 +145,7 @@ namespace Umbraco.Core.Composing.LightInject
/// <inheritdoc />
public void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient)
{
switch (lifetime)
{
case Lifetime.Transient:
Container.Register(serviceType);
break;
case Lifetime.Request:
case Lifetime.Scope:
case Lifetime.Singleton:
Container.Register(serviceType, GetLifetime(lifetime));
break;
default:
throw new NotSupportedException($"Lifetime {lifetime} is not supported.");
}
}
=> Container.Register(serviceType, GetLifetime(lifetime));
/// <inheritdoc />
public void Register(Type serviceType, Type implementingType, Lifetime lifetime = Lifetime.Transient)
@@ -174,22 +167,41 @@ namespace Umbraco.Core.Composing.LightInject
/// <inheritdoc />
public void Register<TService>(Func<IFactory, TService> factory, Lifetime lifetime = Lifetime.Transient)
where TService : class
{
switch (lifetime)
{
case Lifetime.Transient:
Container.Register(f => factory(this));
break;
case Lifetime.Request:
case Lifetime.Scope:
case Lifetime.Singleton:
Container.Register(f => factory(this), GetLifetime(lifetime));
break;
default:
throw new NotSupportedException($"Lifetime {lifetime} is not supported.");
}
Container.Register(f => factory(this), GetLifetime(lifetime));
}
/// <inheritdoc />
public void Register(Type serviceType, object instance)
=> Container.RegisterInstance(serviceType, instance);
/// <inheritdoc />
public void RegisterFor<TService, TTarget>(Lifetime lifetime = Lifetime.Transient)
where TService : class
=> RegisterFor<TService, TTarget>(typeof(TService), lifetime);
/// <inheritdoc />
public void RegisterFor<TService, TTarget>(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<TTarget>(), GetLifetime(lifetime));
}
/// <inheritdoc />
public void RegisterFor<TService, TTarget>(Func<IFactory, TService> 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<TTarget>(), GetLifetime(lifetime));
}
/// <inheritdoc />
public void RegisterFor<TService, TTarget>(TService instance)
where TService : class
=> Container.RegisterInstance(typeof(TService), instance, GetTargetedServiceName<TTarget>());
private ILifetime GetLifetime(Lifetime lifetime)
{
switch (lifetime)
@@ -207,10 +219,6 @@ namespace Umbraco.Core.Composing.LightInject
}
}
/// <inheritdoc />
public void RegisterInstance(Type serviceType, object instance)
=> Container.RegisterInstance(serviceType, instance);
/// <inheritdoc />
public void RegisterAuto(Type serviceBaseType)
{
@@ -223,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
//
///// <inheritdoc />
//public void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, TDependency> factory)
// => Container.RegisterConstructorDependency((f, x) => factory(this, x));
//
///// <inheritdoc />
//public void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, object[], TDependency> factory)
// => Container.RegisterConstructorDependency((f, x, a) => factory(this, x, a));
#endregion
#region Control
@@ -256,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<ILifetime> lifetime, Func<Type, Type, bool> shouldRegister, Func<Type, Type, string> 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
}
}

View File

@@ -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!

View File

@@ -11,7 +11,7 @@ namespace Umbraco.Core.Composing
/// <typeparam name="TItem">The type of the items.</typeparam>
public abstract class OrderedCollectionBuilderBase<TBuilder, TCollection, TItem> : CollectionBuilderBase<TBuilder, TCollection, TItem>
where TBuilder : OrderedCollectionBuilderBase<TBuilder, TCollection, TItem>
where TCollection : IBuilderCollection<TItem>
where TCollection : class, IBuilderCollection<TItem>
{
protected abstract TBuilder This { get; }

View File

@@ -11,22 +11,32 @@
public static void Register<TService, TImplementing>(this IRegister register, Lifetime lifetime = Lifetime.Transient)
=> register.Register(typeof(TService), typeof(TImplementing), lifetime);
/// <summary>
/// Registers a service with an implementation type, for a target.
/// </summary>
public static void RegisterFor<TService, TImplementing, TTarget>(this IRegister register, Lifetime lifetime = Lifetime.Transient)
where TService : class
=> register.RegisterFor<TService, TTarget>(typeof(TImplementing), lifetime);
/// <summary>
/// Registers a service as its own implementation.
/// </summary>
public static void Register<TService>(this IRegister register, Lifetime lifetime = Lifetime.Transient)
where TService : class
=> register.Register(typeof(TService), lifetime);
/// <summary>
/// Registers a service with an implementing instance.
/// </summary>
public static void RegisterInstance<TService>(this IRegister register, TService instance)
=> register.RegisterInstance(typeof(TService), instance);
public static void Register<TService>(this IRegister register, TService instance)
where TService : class
=> register.Register(typeof(TService), instance);
/// <summary>
/// Registers a base type for auto-registration.
/// </summary>
public static void RegisterAuto<TServiceBase>(this IRegister register)
where TServiceBase : class
=> register.RegisterAuto(typeof(TServiceBase));
}
}

View File

@@ -0,0 +1,18 @@
namespace Umbraco.Core.Composing
{
/// <summary>
/// Provides a base class for targeted service factories.
/// </summary>
/// <typeparam name="TService"></typeparam>
public abstract class TargetedServiceFactory<TService>
{
private readonly IFactory _factory;
protected TargetedServiceFactory(IFactory factory)
{
_factory = factory;
}
public TService For<TTarget>() => _factory.GetInstanceFor<TService, TTarget>();
}
}

View File

@@ -12,7 +12,7 @@ namespace Umbraco.Core.Composing
/// <typeparam name="TItem">The type of the items.</typeparam>
public abstract class WeightedCollectionBuilderBase<TBuilder, TCollection, TItem> : CollectionBuilderBase<TBuilder, TCollection, TItem>
where TBuilder : WeightedCollectionBuilderBase<TBuilder, TCollection, TItem>
where TCollection : IBuilderCollection<TItem>
where TCollection : class, IBuilderCollection<TItem>
{
protected abstract TBuilder This { get; }

View File

@@ -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);

View File

@@ -0,0 +1,11 @@
using Umbraco.Core.Composing;
namespace Umbraco.Core.IO
{
public class SupportingFileSystems : TargetedServiceFactory<IFileSystem>
{
public SupportingFileSystems(IFactory factory)
: base(factory)
{ }
}
}

View File

@@ -196,6 +196,7 @@
<Compile Include="Composing\LightInject\LightInjectContainer.cs" />
<Compile Include="Composing\LightInject\MixedLightInjectScopeManagerProvider.cs" />
<Compile Include="Composing\OrderedCollectionBuilderBase.cs" />
<Compile Include="Composing\TargetedServiceFactory.cs" />
<Compile Include="Composing\TypeFinder.cs" />
<Compile Include="Composing\TypeHelper.cs" />
<Compile Include="Composing\TypeLoader.cs" />
@@ -343,6 +344,7 @@
<Compile Include="IO\IMediaPathScheme.cs" />
<Compile Include="IO\MediaPathSchemes\OriginalMediaPathScheme.cs" />
<Compile Include="IO\MediaPathSchemes\TwoGuidsMediaPathScheme.cs" />
<Compile Include="IO\SupportingFileSystems.cs" />
<Compile Include="KeyValuePairExtensions.cs" />
<Compile Include="Logging\IProfilingLogger.cs" />
<Compile Include="Logging\LogHttpRequest.cs" />

View File

@@ -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();

View File

@@ -1,5 +1,4 @@
using System;
using System.Web;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Exceptions;
@@ -11,7 +10,7 @@ namespace Umbraco.Web.Composing
/// </summary>
/// <typeparam name="TModule">The type of the injected module.</typeparam>
public abstract class ModuleInjector<TModule> : IHttpModule
where TModule : IHttpModule
where TModule : class, IHttpModule
{
protected TModule Module { get; private set; }