Cleanup registrations

This commit is contained in:
Stephan
2018-07-23 08:56:08 +02:00
parent a00f2f0bb9
commit d2376bf4e3
19 changed files with 102 additions and 84 deletions

View File

@@ -1,4 +1,5 @@
using Umbraco.Core.Configuration.UmbracoSettings;
using System.Linq;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -15,11 +16,7 @@ namespace Umbraco.Core.Composing.Composers
container.RegisterSingleton<IFileSystems>(factory => factory.GetInstance<FileSystems>());
// register MediaFileSystem, which can be injected directly
container.RegisterSingleton(factory => factory.GetInstance<IFileSystems>().MediaFileSystem);
// register MediaFileSystem, so that FileSystems can create it
container.Register<IFileSystem, MediaFileSystem>((f, wrappedFileSystem)
=> new MediaFileSystem(wrappedFileSystem, f.GetInstance<IContentSection>(), f.GetInstance<IMediaPathScheme>(), f.GetInstance<ILogger>()));
container.Register/*Singleton*/(factory => factory.GetInstance<IFileSystems>().MediaFileSystem);
return container;
}

View File

@@ -30,7 +30,7 @@ namespace Umbraco.Core.Composing
/// <para>Throws an exception if the container failed to get an instance of the specified type.</para>
/// <para>The arguments are used as dependencies by the container.</para>
/// </remarks>
public static T GetInstance<T>(this IContainer container, object[] args)
public static T GetInstance<T>(this IContainer container, params object[] args)
=> (T) container.GetInstance(typeof(T), args);
/// <summary>

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Umbraco.Core.Composing
{
@@ -43,7 +42,10 @@ namespace Umbraco.Core.Composing
/// <para>Throws an exception if the container failed to get an instance of the specified type.</para>
/// <para>The arguments are used as dependencies by the container.</para>
/// </remarks>
object GetInstance(Type type, object[] args);
// fixme - some restrictions:
// method is not optimized, .Invoke-ing the ctor, no compiled dynamic method
// uses the ctor with most args, always, not trying to figure out which one to use
object GetInstance(Type type, params object[] args);
/// <summary>
/// Tries to get an instance.
@@ -67,13 +69,23 @@ namespace Umbraco.Core.Composing
/// <typeparam name="TService">The type of the service.</typeparam>
IEnumerable<TService> GetAllInstances<TService>();
// fixme
/// <summary>
/// Gets registration for a service.
/// </summary>
/// <param name="serviceType">The type of the service.</param>
/// <returns>The registrations for the service.</returns>
IEnumerable<Registration> GetRegistered(Type serviceType);
#endregion
#region Registry
// notes
// when implementing IContainer, the following rules apply
// - it is possible to register a service, even after some instances of other services have been created
// - it is possible to re-register a service, as long as an instance of that service has not been created
// - once an instance of a service has been created, it is not possible to change its registration
/// <summary>
/// Registers a service as its own implementation.
/// </summary>
@@ -107,6 +119,13 @@ namespace Umbraco.Core.Composing
/// <summary>
/// Registers a base type for auto-registration.
/// </summary>
/// <remarks>
/// <para>Auto-registration means that anytime the container is asked to create an instance
/// of a type deriving from <paramref name="serviceBaseType"/>, it will first register that
/// type automatically.</para>
/// <para>This can be used for instance for views or controllers. Then, one just needs to
/// register a common base class or interface, and the container knows how to create instances.</para>
/// </remarks>
void RegisterAuto(Type serviceBaseType);
/// <summary>
@@ -114,11 +133,6 @@ namespace Umbraco.Core.Composing
/// </summary>
void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient);
// fixme - very LightInject specific? or?
// beware! does NOT work on singletons, see https://github.com/seesharper/LightInject/issues/294
void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, TDependency> factory);
void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, object[], TDependency> factory);
#endregion
#region Control
@@ -134,6 +148,12 @@ namespace Umbraco.Core.Composing
// fixme - document all these
/// <summary>
/// Configures the container for Umbraco.
/// </summary>
/// <remarks>
/// <para></para>
/// </remarks>
IContainer ConfigureForUmbraco();
IContainer ConfigureForWeb();

View File

@@ -62,8 +62,26 @@ namespace Umbraco.Core.Composing.LightInject
=> Container.GetInstance(type, name);
/// <inheritdoc />
public object GetInstance(Type type, object[] args)
=> Container.GetInstance(type, args);
public object GetInstance(Type type, params object[] args)
{
// LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities
//return Container.GetInstance(type, args);
var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault();
if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}.");
var ctorParameters = ctor.GetParameters();
var ctorArgs = new object[ctorParameters.Length];
var i = 0;
foreach (var parameter in ctorParameters)
{
// no! IsInstanceOfType is not ok here
// ReSharper disable once UseMethodIsInstanceOfType
var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
ctorArgs[i++] = arg ?? GetInstance(parameter.ParameterType);
}
return ctor.Invoke(ctorArgs);
}
/// <inheritdoc />
public object TryGetInstance(Type type)
@@ -198,13 +216,16 @@ namespace Umbraco.Core.Composing.LightInject
public void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient)
=> Container.RegisterOrdered(serviceType, implementingTypes, _ => GetLifetime(lifetime));
/// <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));
// 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
@@ -251,9 +272,13 @@ namespace Umbraco.Core.Composing.LightInject
// if looking for a IContainer, and one was passed in args, use it
// this is for collection builders which require the IContainer
//Container.RegisterConstructorDependency((c, i, a) => a.OfType<IContainer>().FirstOrDefault());
// which means that the only way to inject the container into builders is to register it
Container.RegisterInstance<IContainer>(this);
//
// and, the block below is also disabled, because it is ugly
//
//// which means that the only way to inject the container into builders is to register it
//Container.RegisterInstance<IContainer>(this);
//
// instead, we use an explicit GetInstance with arguments implementation
return this;
}