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