Simplify IContainer.CreateInstance

This commit is contained in:
Stephan
2018-11-24 16:41:27 +01:00
parent 392c9ed83b
commit 8b74453c13
4 changed files with 7 additions and 38 deletions

View File

@@ -32,7 +32,6 @@ namespace Umbraco.Core.Composing.Composers
* { }
* }
*
* Note that the ctor parameter MUST be named innerFileSystem. fixme oh yea?
* The ctor can have more parameters that will be resolved by the container.
*
* Register your filesystem, in a component:
@@ -74,7 +73,7 @@ namespace Umbraco.Core.Composing.Composers
// it needs to be registered (not only the interface) because it provides additional
// functionality eg for scoping, and is injected in the scope provider - whereas the
// interface is really for end-users to get access to filesystems.
container.RegisterSingleton(factory => factory.CreateInstance<FileSystems>(new { container} ));
container.RegisterSingleton(factory => factory.CreateInstance<FileSystems>(container));
// register IFileSystems, which gives access too all filesystems
container.RegisterSingleton<IFileSystems>(factory => factory.GetInstance<FileSystems>());

View File

@@ -12,9 +12,6 @@ namespace Umbraco.Core.Composing
/// </summary>
public static class ContainerExtensions
{
private static readonly ConcurrentDictionary<Type, Dictionary<string, Func<object, object>>> ArgumentPropertyGetters
= new ConcurrentDictionary<Type, Dictionary<string, Func<object, object>>>();
/// <summary>
/// Gets an instance of a service.
/// </summary>
@@ -55,35 +52,9 @@ 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 CreateInstance<T>(this IContainer container, IDictionary<string, object> args)
public static T CreateInstance<T>(this IContainer container, params object[] args)
=> (T) container.CreateInstance(typeof(T), args);
/// <summary>
/// Creates an instance with arguments.
/// </summary>
/// <typeparam name="T">The type of the instance.</typeparam>
/// <param name="container">The container.</param>
/// <param name="args">Arguments.</param>
/// <returns>An instance of the specified type.</returns>
/// <remarks>
/// <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 CreateInstance<T>(this IContainer container, object args)
{
var typeOfArgs = args.GetType();
var getters = ArgumentPropertyGetters.GetOrAdd(typeOfArgs, type =>
args.GetType()
.GetProperties()
.ToDictionary(x => x.Name, x => ReflectionUtilities.EmitMethodUnsafe<Func<object, object>>(x.GetMethod)));
var argsDictionary = new Dictionary<string, object>();
foreach (var (name, getter) in getters)
argsDictionary[name] = getter(args);
return (T) container.CreateInstance(typeof(T), argsDictionary);
}
/// <summary>
/// Registers a service with an implementation type.
/// </summary>
@@ -140,7 +111,7 @@ namespace Umbraco.Core.Composing
// register the builder
// use a factory so we don't have to self-register the container
container.RegisterSingleton(factory => factory.CreateInstance<TBuilder>(new Dictionary<string, object> {{ "container", container }} ));
container.RegisterSingleton(factory => factory.CreateInstance<TBuilder>(container));
// initialize and return the builder
return container.GetInstance<TBuilder>();
@@ -158,7 +129,7 @@ namespace Umbraco.Core.Composing
/// <para>The arguments are used as dependencies by the container. Other dependencies
/// are retrieved from the container.</para>
/// </remarks>
public static object CreateInstance(this IContainer container, Type type, IDictionary<string, object> args)
public static object CreateInstance(this IContainer container, Type type, params object[] args)
{
// LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities
// including the most annoying one, which is that it does not work on singletons (hard to fix)
@@ -180,8 +151,7 @@ namespace Umbraco.Core.Composing
{
// no! IsInstanceOfType is not ok here
// ReSharper disable once UseMethodIsInstanceOfType
// fixme so we just ignore the names?
var arg = args?.Values.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
ctorArgs[i++] = arg ?? container.GetInstance(parameter.ParameterType);
}
return ctor.Invoke(ctorArgs);

View File

@@ -180,7 +180,7 @@ namespace Umbraco.Core.IO
if (name == null) throw new Exception("panic!");
var shadowWrapper = CreateShadowWrapper(supporting, "typed/" + name);
return _container.CreateInstance<TFileSystem>(new { innerFileSystem = shadowWrapper });
return _container.CreateInstance<TFileSystem>(shadowWrapper);
})).Value;
}

View File

@@ -47,7 +47,7 @@ namespace Umbraco.Tests.Composing
public void CanRegisterSingletonWithCreate()
{
var container = CreateContainer();
container.RegisterSingleton(c => c.CreateInstance<TestClass3>(new Dictionary<string, object>{{"c", new TestClass1()}}));
container.RegisterSingleton(c => c.CreateInstance<TestClass3>(new TestClass1()));
var s1 = container.GetInstance<TestClass3>();
var s2 = container.GetInstance<TestClass3>();
Assert.AreSame(s1, s2);