// Copyright (c) .NET Foundation. 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.Threading; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Mvc.ViewFeatures { public class ViewDataDictionaryControllerPropertyActivator : IControllerPropertyActivator { private readonly Func[]> _getPropertiesToActivate; private readonly IModelMetadataProvider _modelMetadataProvider; private ConcurrentDictionary[]> _activateActions; private bool _initialized; private object _initializeLock = new object(); public ViewDataDictionaryControllerPropertyActivator(IModelMetadataProvider modelMetadataProvider) { _modelMetadataProvider = modelMetadataProvider; _getPropertiesToActivate = GetPropertiesToActivate; } public void Activate(ControllerContext actionContext, object controller) { LazyInitializer.EnsureInitialized( ref _activateActions, ref _initialized, ref _initializeLock); var controllerType = controller.GetType(); var propertiesToActivate = _activateActions.GetOrAdd( controllerType, _getPropertiesToActivate); for (var i = 0; i < propertiesToActivate.Length; i++) { var activateInfo = propertiesToActivate[i]; activateInfo.Activate(controller, actionContext); } } public Action GetActivatorDelegate(ControllerActionDescriptor actionDescriptor) { var controllerType = actionDescriptor.ControllerTypeInfo?.AsType(); if (controllerType == null) { throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( nameof(actionDescriptor.ControllerTypeInfo), nameof(actionDescriptor)), nameof(actionDescriptor)); } var propertiesToActivate = GetPropertiesToActivate(controllerType); void Activate(ControllerContext controllerContext, object controller) { for (var i = 0; i < propertiesToActivate.Length; i++) { var activateInfo = propertiesToActivate[i]; activateInfo.Activate(controller, controllerContext); } } return Activate; } private PropertyActivator[] GetPropertiesToActivate(Type type) { var activators = PropertyActivator.GetPropertiesToActivate( type, typeof(ViewDataDictionaryAttribute), p => new PropertyActivator(p, GetViewDataDictionary)); return activators; } private ViewDataDictionary GetViewDataDictionary(ControllerContext context) { return new ViewDataDictionary( _modelMetadataProvider, context.ModelState); } } }