87 lines
3.0 KiB
C#
87 lines
3.0 KiB
C#
using System;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
namespace Microsoft.AspNet.CoreServices
|
|
{
|
|
/// <summary>
|
|
/// Helper code for the various activator services.
|
|
/// </summary>
|
|
public static class ActivatorUtilities
|
|
{
|
|
/// <summary>
|
|
/// Retrieve an instance of the given type from the service provider. If one is not found then instantiate it directly.
|
|
/// </summary>
|
|
/// <param name="services"></param>
|
|
/// <param name="type"></param>
|
|
/// <returns></returns>
|
|
public static object GetServiceOrCreateInstance(IServiceProvider services, Type type)
|
|
{
|
|
return GetServiceNoExceptions(services, type) ?? CreateInstance(services, type);
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "IServiceProvider may throw unknown exceptions")]
|
|
private static object GetServiceNoExceptions(IServiceProvider services, Type type)
|
|
{
|
|
try
|
|
{
|
|
return services.GetService(type);
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Instantiate an object of the given type, using constructor service injection if possible.
|
|
/// </summary>
|
|
/// <param name="services"></param>
|
|
/// <param name="type"></param>
|
|
/// <returns></returns>
|
|
public static object CreateInstance(IServiceProvider services, Type type)
|
|
{
|
|
return CreateFactory(type).Invoke(services);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a factory to instantiate a type using constructor service injection if possible.
|
|
/// </summary>
|
|
/// <param name="type"></param>
|
|
/// <returns></returns>
|
|
public static Func<IServiceProvider, object> CreateFactory(Type type)
|
|
{
|
|
if (type == null)
|
|
{
|
|
throw new ArgumentNullException("type");
|
|
}
|
|
|
|
ConstructorInfo[] constructors = type.GetTypeInfo()
|
|
.DeclaredConstructors
|
|
.Where(IsInjectable)
|
|
.ToArray();
|
|
|
|
if (constructors.Length == 1)
|
|
{
|
|
ParameterInfo[] parameters = constructors[0].GetParameters();
|
|
return services =>
|
|
{
|
|
var args = new object[parameters.Length];
|
|
for (int index = 0; index != parameters.Length; ++index)
|
|
{
|
|
args[index] = services.GetService(parameters[index].ParameterType);
|
|
}
|
|
return Activator.CreateInstance(type, args);
|
|
};
|
|
}
|
|
return _ => Activator.CreateInstance(type);
|
|
}
|
|
|
|
private static bool IsInjectable(ConstructorInfo constructor)
|
|
{
|
|
return constructor.IsPublic && constructor.GetParameters().Length != 0;
|
|
}
|
|
}
|
|
}
|