// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Reflection; using Microsoft.AspNet.Cryptography; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.Internal; namespace Microsoft.AspNet.DataProtection { /// /// Extension methods for working with . /// internal static class ActivatorExtensions { /// /// Creates an instance of and ensures /// that it is assignable to . /// public static T CreateInstance(this IActivator activator, [NotNull] string implementationTypeName) where T : class { return activator.CreateInstance(typeof(T), implementationTypeName) as T ?? CryptoUtil.Fail("CreateInstance returned null."); } /// /// Returns a given an . /// Guaranteed to return non-null, even if is null. /// public static IActivator GetActivator(this IServiceProvider serviceProvider) { return (serviceProvider != null) ? (serviceProvider.GetService() ?? new SimpleActivator(serviceProvider)) : SimpleActivator.DefaultWithoutServices; } /// /// A simplified default implementation of that understands /// how to call ctors which take . /// private sealed class SimpleActivator : IActivator { /// /// A default whose wrapped is null. /// internal static readonly SimpleActivator DefaultWithoutServices = new SimpleActivator(null); private readonly IServiceProvider _services; public SimpleActivator(IServiceProvider services) { _services = services; } public object CreateInstance(Type expectedBaseType, string implementationTypeName) { // Would the assignment even work? var implementationType = Type.GetType(implementationTypeName, throwOnError: true); expectedBaseType.AssertIsAssignableFrom(implementationType); // If no IServiceProvider was specified, prefer .ctor() [if it exists] if (_services == null) { var ctorParameterless = implementationType.GetConstructor(Type.EmptyTypes); if (ctorParameterless != null) { return Activator.CreateInstance(implementationType); } } // If an IServiceProvider was specified or if .ctor() doesn't exist, prefer .ctor(IServiceProvider) [if it exists] var ctorWhichTakesServiceProvider = implementationType.GetConstructor(new Type[] { typeof(IServiceProvider) }); if (ctorWhichTakesServiceProvider != null) { return ctorWhichTakesServiceProvider.Invoke(new[] { _services }); } // Finally, prefer .ctor() as an ultimate fallback. // This will throw if the ctor cannot be called. return Activator.CreateInstance(implementationType); } } } }