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; } } }