using System; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Linq; using System.Linq.Expressions; 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.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; } public static Func Create(Type instanceType) where TBase : class { Contract.Assert(instanceType != null); NewExpression newInstanceExpression = Expression.New(instanceType); return Expression.Lambda>(newInstanceExpression).Compile(); } public static Func Create() where TInstance : class { return Create(typeof(TInstance)); } public static Func Create(Type instanceType) { Contract.Assert(instanceType != null); return Create(instanceType); } } }