using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
namespace Microsoft.AspNet.CoreServices
{
///
/// Helper code for the various activator services.
///
public static class ActivatorUtilities
{
///
/// Retrieve an instance of the given type from the service provider. If one is not found then instantiate it directly.
///
///
///
///
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;
}
}
///
/// Instantiate an object of the given type, using constructor service injection if possible.
///
///
///
///
public static object CreateInstance(IServiceProvider services, Type type)
{
return CreateFactory(type).Invoke(services);
}
///
/// Creates a factory to instantiate a type using constructor service injection if possible.
///
///
///
public static Func CreateFactory(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
ConstructorInfo[] constructors = type
.GetConstructors()
.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;
}
}
}