// 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.Collections.Concurrent; using System.Collections.Generic; using System.Reflection; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.Framework.DependencyInjection; namespace Microsoft.AspNet.Mvc { /// /// Represents the that is registered by default. /// public class DefaultControllerActivator : IControllerActivator { private readonly Func[]> _getPropertiesToActivate; private readonly IReadOnlyDictionary> _valueAccessorLookup; private readonly ConcurrentDictionary[]> _injectActions; /// /// Initializes a new instance of the DefaultControllerActivator class. /// public DefaultControllerActivator() { _valueAccessorLookup = CreateValueAccessorLookup(); _injectActions = new ConcurrentDictionary[]>(); _getPropertiesToActivate = type => PropertyActivator.GetPropertiesToActivate(type, typeof(ActivateAttribute), CreateActivateInfo); } /// /// Activates the specified controller by using the specified action context. /// /// The controller to activate. /// The context of the executing action. public void Activate([NotNull] object controller, [NotNull] ActionContext context) { var controllerType = controller.GetType(); var controllerTypeInfo = controllerType.GetTypeInfo(); if (controllerTypeInfo.IsValueType) { var message = Resources.FormatValueTypesCannotBeActivated(GetType().FullName); throw new InvalidOperationException(message); } var propertiesToActivate = _injectActions.GetOrAdd(controllerType, _getPropertiesToActivate); for (var i = 0; i < propertiesToActivate.Length; i++) { var activateInfo = propertiesToActivate[i]; activateInfo.Activate(controller, context); } } protected virtual IReadOnlyDictionary> CreateValueAccessorLookup() { var dictionary = new Dictionary> { { typeof(ActionContext), (context) => context }, { typeof(HttpContext), (context) => context.HttpContext }, { typeof(HttpRequest), (context) => context.HttpContext.Request }, { typeof(HttpResponse), (context) => context.HttpContext.Response }, { typeof(ViewDataDictionary), (context) => { var serviceProvider = context.HttpContext.RequestServices; return new ViewDataDictionary( serviceProvider.GetRequiredService(), context.ModelState); } } }; return dictionary; } private PropertyActivator CreateActivateInfo( PropertyInfo property) { Func valueAccessor; if (!_valueAccessorLookup.TryGetValue(property.PropertyType, out valueAccessor)) { valueAccessor = (actionContext) => { var serviceProvider = actionContext.HttpContext.RequestServices; return serviceProvider.GetRequiredService(property.PropertyType); }; } return new PropertyActivator(property, valueAccessor); } } }