Makes Container.CreateInstance into an extension
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
@@ -172,5 +173,43 @@ namespace Umbraco.Core.Composing
|
||||
// initialize and return the builder
|
||||
return container.GetInstance<TBuilder>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of a service, with arguments.
|
||||
/// </summary>
|
||||
/// <param name="container"></param>
|
||||
/// <param name="type">The type of the instance.</param>
|
||||
/// <param name="args">Named arguments.</param>
|
||||
/// <returns>An instance of the specified type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The instance type does not need to be registered into the container.</para>
|
||||
/// <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)
|
||||
{
|
||||
// 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)
|
||||
//return Container.GetInstance(type, args);
|
||||
|
||||
// this method is essentially used to build singleton instances, so it is assumed that it would be
|
||||
// more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do
|
||||
// here - this can be discussed
|
||||
|
||||
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?.Values.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
|
||||
ctorArgs[i++] = arg ?? container.GetInstance(parameter.ParameterType);
|
||||
}
|
||||
return ctor.Invoke(ctorArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Composing.LightInject;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
@@ -77,19 +78,6 @@ namespace Umbraco.Core.Composing
|
||||
/// <returns>The registrations for the service.</returns>
|
||||
IEnumerable<Registration> GetRegistered(Type serviceType);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of a service, with arguments.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the instance.</param>
|
||||
/// <param name="args">Named arguments.</param>
|
||||
/// <returns>An instance of the specified type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The instance type does not need to be registered into the container.</para>
|
||||
/// <para>The arguments are used as dependencies by the container. Other dependencies
|
||||
/// are retrieved from the container.</para>
|
||||
/// </remarks>
|
||||
object CreateInstance(Type type, IDictionary<string, object> args);
|
||||
|
||||
/// <summary>
|
||||
/// Releases an instance.
|
||||
/// </summary>
|
||||
|
||||
@@ -125,33 +125,6 @@ namespace Umbraco.Core.Composing.LightInject
|
||||
public IEnumerable<Registration> GetRegistered(Type type)
|
||||
=> Container.AvailableServices.Where(x => x.ServiceType == type).Select(x => new Registration(x.ServiceType, x.ServiceName));
|
||||
|
||||
/// <inheritdoc />
|
||||
public object CreateInstance(Type type, IDictionary<string, 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)
|
||||
//return Container.GetInstance(type, args);
|
||||
|
||||
// this method is essentially used to build singleton instances, so it is assumed that it would be
|
||||
// more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do
|
||||
// here - this can be discussed
|
||||
|
||||
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?.Values.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
|
||||
ctorArgs[i++] = arg ?? GetInstance(parameter.ParameterType);
|
||||
}
|
||||
return ctor.Invoke(ctorArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Release(object instance)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user