diff --git a/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActivator.cs b/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActivator.cs index 615d614ef4..d44e93dd6b 100644 --- a/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActivator.cs +++ b/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActivator.cs @@ -2,7 +2,6 @@ // 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 Microsoft.Framework.DependencyInjection; namespace Microsoft.AspNet.Mvc @@ -12,17 +11,21 @@ namespace Microsoft.AspNet.Mvc /// public class DefaultControllerActivator : IControllerActivator { - private static readonly Func _createControllerFactory = - type => ActivatorUtilities.CreateFactory(type, Type.EmptyTypes); - - private readonly ConcurrentDictionary _controllerFactories = - new ConcurrentDictionary(); + private readonly ITypeActivatorCache _typeActivatorCache; + /// + /// Creates a new . + /// + /// The . + public DefaultControllerActivator(ITypeActivatorCache typeActivatorCache) + { + _typeActivatorCache = typeActivatorCache; + } /// public object Create([NotNull] ActionContext actionContext, [NotNull] Type controllerType) { - var factory = _controllerFactories.GetOrAdd(controllerType, _createControllerFactory); - return factory(actionContext.HttpContext.RequestServices, arguments: null); + var serviceProvider = actionContext.HttpContext.RequestServices; + return _typeActivatorCache.CreateInstance(serviceProvider, controllerType); } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/DefaultTypeActivatorCache.cs b/src/Microsoft.AspNet.Mvc.Core/DefaultTypeActivatorCache.cs new file mode 100644 index 0000000000..6d17988c93 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Core/DefaultTypeActivatorCache.cs @@ -0,0 +1,30 @@ +// 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 Microsoft.Framework.DependencyInjection; + +namespace Microsoft.AspNet.Mvc +{ + /// + /// Caches instances produced by + /// . + /// + public class DefaultTypeActivatorCache : ITypeActivatorCache + { + private readonly Func _createFactory = + (type) => ActivatorUtilities.CreateFactory(type, Type.EmptyTypes); + private readonly ConcurrentDictionary _typeActivatorCache = + new ConcurrentDictionary(); + + /// + public TInstance CreateInstance( + [NotNull] IServiceProvider serviceProvider, + [NotNull] Type implementationType) + { + var createFactory = _typeActivatorCache.GetOrAdd(implementationType, _createFactory); + return (TInstance)createFactory(serviceProvider, arguments: null); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/DefaultValidationExcludeFiltersProvider.cs b/src/Microsoft.AspNet.Mvc.Core/DefaultValidationExcludeFiltersProvider.cs index b649e03773..6a303e6dd6 100644 --- a/src/Microsoft.AspNet.Mvc.Core/DefaultValidationExcludeFiltersProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/DefaultValidationExcludeFiltersProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using Microsoft.AspNet.Mvc.ModelBinding; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; namespace Microsoft.AspNet.Mvc.OptionDescriptors @@ -14,16 +13,15 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors : OptionDescriptorBasedProvider, IValidationExcludeFiltersProvider { /// - /// Initializes a new instance of the DefaultBodyValidationExcludeFiltersProvider class. + /// Initializes a new instance of the class. /// /// An accessor to the configured for this application. - /// An instance used to instantiate types. - /// A instance that retrieves services from the - /// service collection. + /// The cache. + /// The . public DefaultValidationExcludeFiltersProvider(IOptions optionsAccessor, - ITypeActivator typeActivator, - IServiceProvider serviceProvider) - : base(optionsAccessor.Options.ValidationExcludeFilters, typeActivator, serviceProvider) + ITypeActivatorCache typeActivatorCache, + IServiceProvider serviceProvider) + : base(optionsAccessor.Options.ValidationExcludeFilters, typeActivatorCache, serviceProvider) { } diff --git a/src/Microsoft.AspNet.Mvc.Core/Filters/FilterCollectionExtensions.cs b/src/Microsoft.AspNet.Mvc.Core/Filters/FilterCollectionExtensions.cs index a4812253af..a258a4c1af 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Filters/FilterCollectionExtensions.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Filters/FilterCollectionExtensions.cs @@ -19,7 +19,8 @@ namespace Microsoft.AspNet.Mvc /// Type representing an . /// An representing the added type. /// - /// Filter instances will be created using . + /// Filter instances will be created using + /// . /// Use to register a service as a filter. /// public static IFilter Add( @@ -37,7 +38,8 @@ namespace Microsoft.AspNet.Mvc /// The order of the added filter. /// An representing the added type. /// - /// Filter instances will be created using . + /// Filter instances will be created using + /// . /// Use to register a service as a filter. /// public static IFilter Add( diff --git a/src/Microsoft.AspNet.Mvc.Core/Filters/TypeFilterAttribute.cs b/src/Microsoft.AspNet.Mvc.Core/Filters/TypeFilterAttribute.cs index d932a4a033..113c845503 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Filters/TypeFilterAttribute.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Filters/TypeFilterAttribute.cs @@ -3,7 +3,7 @@ using System; using System.Diagnostics; -using Microsoft.AspNet.Mvc.Core; +using System.Linq; using Microsoft.Framework.DependencyInjection; namespace Microsoft.AspNet.Mvc @@ -12,6 +12,8 @@ namespace Microsoft.AspNet.Mvc [DebuggerDisplay("TypeFilter: Type={ImplementationType} Order={Order}")] public class TypeFilterAttribute : Attribute, IFilterFactory, IOrderedFilter { + private ObjectFactory _factory; + public TypeFilterAttribute([NotNull] Type type) { ImplementationType = type; @@ -25,18 +27,14 @@ namespace Microsoft.AspNet.Mvc public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider) { - var activator = serviceProvider.GetRequiredService(); - var obj = activator.CreateInstance(serviceProvider, ImplementationType, Arguments ?? new object[0]); - - var filter = obj as IFilter; - if (filter == null) + if (_factory == null) { - throw new InvalidOperationException(Resources.FormatFilterFactoryAttribute_TypeMustImplementIFilter( - typeof(TypeFilterAttribute).Name, - typeof(IFilter).Name)); + var argumentTypes = Arguments?.Select(a => a.GetType())?.ToArray(); + + _factory = ActivatorUtilities.CreateFactory(ImplementationType, argumentTypes ?? Type.EmptyTypes); } - return filter; + return (IFilter)_factory(serviceProvider, Arguments); } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/DefaultInputFormattersProvider.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/DefaultInputFormattersProvider.cs index 651695fe29..6b5e9b4d31 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Formatters/DefaultInputFormattersProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/DefaultInputFormattersProvider.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; namespace Microsoft.AspNet.Mvc.OptionDescriptors @@ -16,13 +15,14 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors /// Initializes a new instance of the DefaultInputFormattersProvider class. /// /// An accessor to the configured for this application. - /// An instance used to instantiate types. + /// As instance that creates an instance + /// of type . /// A instance that retrieves services from the /// service collection. public DefaultInputFormattersProvider(IOptions optionsAccessor, - ITypeActivator typeActivator, + ITypeActivatorCache typeActivatorCache, IServiceProvider serviceProvider) - : base(optionsAccessor.Options.InputFormatters, typeActivator, serviceProvider) + : base(optionsAccessor.Options.InputFormatters, typeActivatorCache, serviceProvider) { } diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/DefaultOutputFormattersProvider.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/DefaultOutputFormattersProvider.cs index 86163d7663..39df20771a 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Formatters/DefaultOutputFormattersProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/DefaultOutputFormattersProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using Microsoft.AspNet.Mvc.OptionDescriptors; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; namespace Microsoft.AspNet.Mvc @@ -17,13 +16,14 @@ namespace Microsoft.AspNet.Mvc /// Initializes a new instance of the DefaultOutputFormattersProvider class. /// /// An accessor to the configured for this application. - /// An instance used to instantiate types. + /// As instance that creates an instance + /// of type . /// A instance that retrieves services from the /// service collection. public DefaultOutputFormattersProvider(IOptions optionsAccessor, - ITypeActivator typeActivator, - IServiceProvider serviceProvider) - : base(optionsAccessor.Options.OutputFormatters, typeActivator, serviceProvider) + ITypeActivatorCache typeActivatorCache, + IServiceProvider serviceProvider) + : base(optionsAccessor.Options.OutputFormatters, typeActivatorCache, serviceProvider) { } diff --git a/src/Microsoft.AspNet.Mvc.Core/ITypeActivatorCache.cs b/src/Microsoft.AspNet.Mvc.Core/ITypeActivatorCache.cs new file mode 100644 index 0000000000..3397ccf661 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Core/ITypeActivatorCache.cs @@ -0,0 +1,22 @@ +// 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; + +namespace Microsoft.AspNet.Mvc +{ + /// + /// Caches instances produced by + /// . + /// + public interface ITypeActivatorCache + { + /// + /// Creates an instance of . + /// + /// The used to resolve dependencies for + /// . + /// The of the to create. + TInstance CreateInstance(IServiceProvider serviceProvider, Type optionType); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultModelBindersProvider.cs b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultModelBindersProvider.cs index d1b80fe6ab..c61c9a00f5 100644 --- a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultModelBindersProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultModelBindersProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using Microsoft.AspNet.Mvc.ModelBinding; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; namespace Microsoft.AspNet.Mvc.OptionDescriptors @@ -16,14 +15,15 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors /// Initializes a new instance of the DefaultModelBindersProvider class. /// /// An accessor to the configured for this application. - /// An instance used to instantiate types. + /// As instance that creates an instance + /// of type . /// A instance that retrieves services from the /// service collection. public DefaultModelBindersProvider( IOptions optionsAccessor, - ITypeActivator typeActivator, + ITypeActivatorCache typeActivatorCache, IServiceProvider serviceProvider) - : base(optionsAccessor.Options.ModelBinders, typeActivator, serviceProvider) + : base(optionsAccessor.Options.ModelBinders, typeActivatorCache, serviceProvider) { } diff --git a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultModelValidatorProviderProvider.cs b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultModelValidatorProviderProvider.cs index d4322a67d8..87cf7815a3 100644 --- a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultModelValidatorProviderProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultModelValidatorProviderProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using Microsoft.AspNet.Mvc.ModelBinding; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; namespace Microsoft.AspNet.Mvc.OptionDescriptors @@ -17,14 +16,15 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors /// Initializes a new instance of the class. /// /// An accessor to the configured for this application. - /// An instance used to instantiate types. + /// As instance that creates an instance + /// of type . /// A instance that retrieves services from the /// service collection. public DefaultModelValidatorProviderProvider( IOptions optionsAccessor, - ITypeActivator typeActivator, + ITypeActivatorCache typeActivatorCache, IServiceProvider serviceProvider) - : base(optionsAccessor.Options.ModelValidatorProviders, typeActivator, serviceProvider) + : base(optionsAccessor.Options.ModelValidatorProviders, typeActivatorCache, serviceProvider) { } diff --git a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultValueProviderFactoryProvider.cs b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultValueProviderFactoryProvider.cs index 25eacc0f9e..d31393664a 100644 --- a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultValueProviderFactoryProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultValueProviderFactoryProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using Microsoft.AspNet.Mvc.ModelBinding; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; namespace Microsoft.AspNet.Mvc.OptionDescriptors @@ -17,14 +16,15 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors /// Initializes a new instance of the class. /// /// An accessor to the configured for this application. - /// An instance used to instantiate types. + /// As instance that creates + /// an instance of type . /// A instance that retrieves services from the /// service collection. public DefaultValueProviderFactoryProvider( IOptions optionsAccessor, - ITypeActivator typeActivator, + ITypeActivatorCache typeActivatorCache, IServiceProvider serviceProvider) - : base(optionsAccessor.Options.ValueProviderFactories, typeActivator, serviceProvider) + : base(optionsAccessor.Options.ValueProviderFactories, typeActivatorCache, serviceProvider) { } diff --git a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultViewEngineProvider.cs b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultViewEngineProvider.cs index a079d75891..19e6fce394 100644 --- a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultViewEngineProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/DefaultViewEngineProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using Microsoft.AspNet.Mvc.Rendering; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; namespace Microsoft.AspNet.Mvc.OptionDescriptors @@ -16,14 +15,15 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors /// Initializes a new instance of the class. /// /// An accessor to the configured for this application. - /// An instance used to instantiate types. + /// As instance that creates + /// an instance of type . /// A instance that retrieves services from the /// service collection. public DefaultViewEngineProvider( IOptions optionsAccessor, - ITypeActivator typeActivator, + ITypeActivatorCache typeActivatorCache, IServiceProvider serviceProvider) - : base(optionsAccessor.Options.ViewEngines, typeActivator, serviceProvider) + : base(optionsAccessor.Options.ViewEngines, typeActivatorCache, serviceProvider) { } diff --git a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/OptionDescriptorBasedProvider.cs b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/OptionDescriptorBasedProvider.cs index 063188441f..a111566dc1 100644 --- a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/OptionDescriptorBasedProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/OptionDescriptorBasedProvider.cs @@ -15,16 +15,24 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors public abstract class OptionDescriptorBasedProvider { private readonly IEnumerable> _optionDescriptors; - private readonly ITypeActivator _typeActivator; + private ITypeActivatorCache _typeActivatorCache; private readonly IServiceProvider _serviceProvider; + /// + /// Initializes a new instance of the class. + /// + /// An enumerable of . + /// As instance that creates an + /// instance of type . + /// A instance that retrieves services from the + /// service collection. public OptionDescriptorBasedProvider( [NotNull] IEnumerable> optionDescriptors, - [NotNull] ITypeActivator typeActivator, + [NotNull] ITypeActivatorCache typeActivatorCache, [NotNull] IServiceProvider serviceProvider) { _optionDescriptors = optionDescriptors; - _typeActivator = typeActivator; + _typeActivatorCache = typeActivatorCache; _serviceProvider = serviceProvider; } @@ -41,8 +49,7 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors var instance = descriptor.Instance; if (instance == null) { - instance = (TOption)_typeActivator.CreateInstance(_serviceProvider, - descriptor.OptionType); + instance = _typeActivatorCache.CreateInstance(_serviceProvider, descriptor.OptionType); } result.Add(instance); diff --git a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/DefaultViewComponentInvoker.cs b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/DefaultViewComponentInvoker.cs index 30d632c6ad..2aca9ca27f 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/DefaultViewComponentInvoker.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/DefaultViewComponentInvoker.cs @@ -14,20 +14,20 @@ namespace Microsoft.AspNet.Mvc public class DefaultViewComponentInvoker : IViewComponentInvoker { private readonly IServiceProvider _serviceProvider; - private readonly ITypeActivator _activator; + private readonly ITypeActivatorCache _typeActivatorCache; private readonly TypeInfo _componentType; private readonly IViewComponentActivator _viewComponentActivator; private readonly object[] _args; public DefaultViewComponentInvoker( [NotNull] IServiceProvider serviceProvider, - [NotNull] ITypeActivator activator, + [NotNull] ITypeActivatorCache typeActivatorCache, [NotNull] IViewComponentActivator viewComponentActivator, [NotNull] TypeInfo componentType, object[] args) { _serviceProvider = serviceProvider; - _activator = activator; + _typeActivatorCache = typeActivatorCache; _componentType = componentType; _viewComponentActivator = viewComponentActivator; _args = args ?? new object[0]; @@ -77,7 +77,7 @@ namespace Microsoft.AspNet.Mvc private object CreateComponent([NotNull] ViewContext context) { - var component = _activator.CreateInstance(_serviceProvider, _componentType.AsType()); + var component = _typeActivatorCache.CreateInstance(_serviceProvider, _componentType.AsType()); _viewComponentActivator.Activate(component, context); return component; } diff --git a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/DefaultViewComponentInvokerProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/DefaultViewComponentInvokerProvider.cs index fc63aa6d79..a14fbbbbb9 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/DefaultViewComponentInvokerProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/DefaultViewComponentInvokerProvider.cs @@ -9,16 +9,16 @@ namespace Microsoft.AspNet.Mvc public class DefaultViewComponentInvokerProvider : IViewComponentInvokerProvider { private readonly IServiceProvider _serviceProvider; - private readonly ITypeActivator _typeActivator; + private readonly ITypeActivatorCache _typeActivatorCache; private readonly IViewComponentActivator _viewComponentActivator; public DefaultViewComponentInvokerProvider( IServiceProvider serviceProvider, - ITypeActivator typeActivator, + ITypeActivatorCache typeActivatorCache, IViewComponentActivator viewComponentActivator) { _serviceProvider = serviceProvider; - _typeActivator = typeActivator; + _typeActivatorCache = typeActivatorCache; _viewComponentActivator = viewComponentActivator; } @@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Mvc { context.Result = new DefaultViewComponentInvoker( _serviceProvider, - _typeActivator, + _typeActivatorCache, _viewComponentActivator, context.ComponentType, context.Arguments); diff --git a/src/Microsoft.AspNet.Mvc.Core/ViewDataDictionaryOfT.cs b/src/Microsoft.AspNet.Mvc.Core/ViewDataDictionaryOfT.cs index 051d83b11c..b48ba1e9a8 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ViewDataDictionaryOfT.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ViewDataDictionaryOfT.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Mvc /// For use when creating a for a new top-level scope. /// /// - // References may not show up due to ITypeActivator use in RazorPageActivator. + // References may not show up due to ActivatorUtilities use in RazorPageActivator. public ViewDataDictionary( [NotNull] IModelMetadataProvider metadataProvider, [NotNull] ModelStateDictionary modelState) @@ -39,7 +39,7 @@ namespace Microsoft.AspNet.Mvc /// /// /// - // References may not show up due to ITypeActivator use in RazorPageActivator. + // References may not show up due to ActivatorUtilities use in RazorPageActivator. public ViewDataDictionary([NotNull] ViewDataDictionary source) : base(source, declaredModelType: typeof(TModel)) { diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/BindAttribute.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/BindAttribute.cs index 396d5a9b2a..db595d1368 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/BindAttribute.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/BindAttribute.cs @@ -17,6 +17,8 @@ namespace Microsoft.AspNet.Mvc private static readonly Func _defaultFilter = (context, propertyName) => true; + private ObjectFactory _factory; + private Func _predicateFromInclude; /// @@ -79,7 +81,8 @@ namespace Microsoft.AspNet.Mvc { if (PredicateProviderType != null) { - return CreatePredicateFromProviderType(PredicateProviderType); + var factory = GetFactory(); + return CreatePredicateFromProviderType(factory); } else if (Include != null && Include.Length > 0) { @@ -98,8 +101,17 @@ namespace Microsoft.AspNet.Mvc } } + private ObjectFactory GetFactory() + { + if (_factory == null) + { + _factory = ActivatorUtilities.CreateFactory(PredicateProviderType, Type.EmptyTypes); + } + return _factory; + } + private static Func CreatePredicateFromProviderType( - Type predicateProviderType) + ObjectFactory factory) { // Holding state to avoid execessive creation of the provider. var initialized = false; @@ -110,11 +122,8 @@ namespace Microsoft.AspNet.Mvc if (!initialized) { var services = context.OperationBindingContext.HttpContext.RequestServices; - var activator = services.GetService(); - var provider = (IPropertyBindingPredicateProvider)activator.CreateInstance( - services, - predicateProviderType); + var provider = (IPropertyBindingPredicateProvider)factory(services, arguments: null); initialized = true; predicate = provider.PropertyFilter ?? _defaultFilter; diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BinderTypeBasedModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BinderTypeBasedModelBinder.cs index 10f81b33a0..714325c68a 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BinderTypeBasedModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BinderTypeBasedModelBinder.cs @@ -2,6 +2,7 @@ // 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.Tasks; using Microsoft.Framework.DependencyInjection; @@ -14,16 +15,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding /// public class BinderTypeBasedModelBinder : IModelBinder { - private readonly ITypeActivator _typeActivator; - - /// - /// Creates a new instance of . - /// - /// The . - public BinderTypeBasedModelBinder([NotNull] ITypeActivator typeActivator) - { - _typeActivator = typeActivator; - } + private readonly Func _createFactory = + (t) => ActivatorUtilities.CreateFactory(t, Type.EmptyTypes); + private ConcurrentDictionary _typeActivatorCache = + new ConcurrentDictionary(); + public async Task BindModelAsync(ModelBindingContext bindingContext) { @@ -35,8 +31,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding } var requestServices = bindingContext.OperationBindingContext.HttpContext.RequestServices; - var instance = _typeActivator.CreateInstance(requestServices, bindingContext.ModelMetadata.BinderType); - + var createFactory = _typeActivatorCache.GetOrAdd(bindingContext.ModelMetadata.BinderType, _createFactory); + var instance = createFactory(requestServices, arguments: null); + var modelBinder = instance as IModelBinder; if (modelBinder == null) { diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/GenericModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/GenericModelBinder.cs index 178addd3d0..649dd32c67 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/GenericModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/GenericModelBinder.cs @@ -7,27 +7,17 @@ using System.Diagnostics; using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNet.Mvc.ModelBinding.Internal; -using Microsoft.Framework.DependencyInjection; namespace Microsoft.AspNet.Mvc.ModelBinding { public class GenericModelBinder : IModelBinder { - private readonly ITypeActivator _activator; - private readonly IServiceProvider _serviceProvider; - - public GenericModelBinder(IServiceProvider serviceProvider, ITypeActivator activator) - { - _serviceProvider = serviceProvider; - _activator = activator; - } - public async Task BindModelAsync(ModelBindingContext bindingContext) { var binderType = ResolveBinderType(bindingContext.ModelType); if (binderType != null) { - var binder = (IModelBinder)_activator.CreateInstance(_serviceProvider, binderType); + var binder = (IModelBinder)Activator.CreateInstance(binderType); await binder.BindModelAsync(bindingContext); // Was able to resolve a binder type, hence we should tell the model binding system to return diff --git a/src/Microsoft.AspNet.Mvc.Razor/OptionDescriptors/DefaultViewLocationExpanderProvider.cs b/src/Microsoft.AspNet.Mvc.Razor/OptionDescriptors/DefaultViewLocationExpanderProvider.cs index a1052759b2..6db8a46f48 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/OptionDescriptors/DefaultViewLocationExpanderProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/OptionDescriptors/DefaultViewLocationExpanderProvider.cs @@ -17,14 +17,15 @@ namespace Microsoft.AspNet.Mvc.Razor.OptionDescriptors /// Initializes a new instance of the class. /// /// An accessor to the configured for this application. - /// An instance used to instantiate types. + /// A instance that creates a new instance + /// of type . /// A instance that retrieves services from the /// service collection. public DefaultViewLocationExpanderProvider( IOptions optionsAccessor, - ITypeActivator typeActivator, + ITypeActivatorCache typeActivatorCache, IServiceProvider serviceProvider) - : base(optionsAccessor.Options.ViewLocationExpanders, typeActivator, serviceProvider) + : base(optionsAccessor.Options.ViewLocationExpanders, typeActivatorCache, serviceProvider) { } diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorPageActivator.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorPageActivator.cs index 6e0a7feaa7..acff083e4b 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorPageActivator.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorPageActivator.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Reflection; +using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.Framework.DependencyInjection; @@ -14,16 +15,16 @@ namespace Microsoft.AspNet.Mvc.Razor { // Name of the "public TModel Model" property on RazorPage private const string ModelPropertyName = "Model"; - private readonly ITypeActivator _typeActivator; private readonly ConcurrentDictionary _activationInfo; + private readonly IModelMetadataProvider _metadataProvider; /// /// Initializes a new instance of the class. /// - public RazorPageActivator(ITypeActivator typeActivator) + public RazorPageActivator(IModelMetadataProvider metadataProvider) { - _typeActivator = typeActivator; _activationInfo = new ConcurrentDictionary(); + _metadataProvider = metadataProvider; } /// @@ -48,16 +49,15 @@ namespace Microsoft.AspNet.Mvc.Razor if (context.ViewData == null) { // Create ViewDataDictionary(IModelMetadataProvider, ModelStateDictionary). - return (ViewDataDictionary)_typeActivator.CreateInstance(context.HttpContext.RequestServices, - activationInfo.ViewDataDictionaryType, - context.ModelState); + return (ViewDataDictionary)Activator.CreateInstance(activationInfo.ViewDataDictionaryType, + _metadataProvider, + context.ModelState); } else if (context.ViewData.GetType() != activationInfo.ViewDataDictionaryType) { // Create ViewDataDictionary(ViewDataDictionary). - return (ViewDataDictionary)_typeActivator.CreateInstance(context.HttpContext.RequestServices, - activationInfo.ViewDataDictionaryType, - context.ViewData); + return (ViewDataDictionary)Activator.CreateInstance(activationInfo.ViewDataDictionaryType, + context.ViewData); } return context.ViewData; diff --git a/src/Microsoft.AspNet.Mvc.Razor/VirtualPathRazorPageFactory.cs b/src/Microsoft.AspNet.Mvc.Razor/VirtualPathRazorPageFactory.cs index 4793209885..4f07710909 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/VirtualPathRazorPageFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/VirtualPathRazorPageFactory.cs @@ -2,6 +2,7 @@ // 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 Microsoft.Framework.DependencyInjection; namespace Microsoft.AspNet.Mvc.Razor @@ -12,16 +13,13 @@ namespace Microsoft.AspNet.Mvc.Razor /// public class VirtualPathRazorPageFactory : IRazorPageFactory { - private readonly ITypeActivator _activator; private readonly IServiceProvider _serviceProvider; private readonly ICompilerCache _compilerCache; private IRazorCompilationService _razorcompilationService; - public VirtualPathRazorPageFactory(ITypeActivator typeActivator, - IServiceProvider serviceProvider, + public VirtualPathRazorPageFactory(IServiceProvider serviceProvider, ICompilerCache compilerCache) { - _activator = typeActivator; _serviceProvider = serviceProvider; _compilerCache = compilerCache; } @@ -60,10 +58,10 @@ namespace Microsoft.AspNet.Mvc.Razor return null; } - var page = (IRazorPage)_activator.CreateInstance(_serviceProvider, result.CompilationResult.CompiledType); + var page = (IRazorPage)Activator.CreateInstance(result.CompilationResult.CompiledType); page.Path = relativePath; return page; } } -} +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc/MvcServices.cs b/src/Microsoft.AspNet.Mvc/MvcServices.cs index 62f1f5d090..c72994092d 100644 --- a/src/Microsoft.AspNet.Mvc/MvcServices.cs +++ b/src/Microsoft.AspNet.Mvc/MvcServices.cs @@ -37,8 +37,8 @@ namespace Microsoft.AspNet.Mvc typeof(INestedProviderManagerAsync<>), typeof(NestedProviderManagerAsync<>)); yield return describe.Transient(); + yield return describe.Singleton(typeof(ITypeActivatorCache), typeof(DefaultTypeActivatorCache)); yield return describe.Scoped(typeof(IScopedInstance<>), typeof(ScopedInstance<>)); - // Core action discovery, filters and action execution. // These are consumed only when creating action descriptors, then they can be de-allocated @@ -49,8 +49,7 @@ namespace Microsoft.AspNet.Mvc // This has a cache, so it needs to be a singleton yield return describe.Singleton(); - // This has a cache, so it needs to be a singleton - yield return describe.Singleton(); + yield return describe.Transient(); // This accesses per-reqest services yield return describe.Transient(); @@ -78,9 +77,7 @@ namespace Microsoft.AspNet.Mvc yield return describe.Transient, DefaultFilterProvider>(); yield return describe.Transient(); - // Dataflow - ModelBinding, Validation and Formatting - // The DataAnnotationsModelMetadataProvider does significant caching of reflection/attributes // and thus needs to be singleton. yield return describe.Singleton(); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerActivatorTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerActivatorTest.cs index e349e416ee..c155e8dbc9 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerActivatorTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerActivatorTest.cs @@ -17,8 +17,14 @@ namespace Microsoft.AspNet.Mvc public void Create_CreatesInstancesOfTypes(Type type) { // Arrange - var activator = new DefaultControllerActivator(); - var actionContext = new ActionContext(new DefaultHttpContext(), + var activator = new DefaultControllerActivator(new DefaultTypeActivatorCache()); + var serviceProvider = new Mock(MockBehavior.Strict); + + var httpContext = new DefaultHttpContext + { + RequestServices = serviceProvider.Object + }; + var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); // Act @@ -32,12 +38,13 @@ namespace Microsoft.AspNet.Mvc public void Create_TypeActivatesTypesWithServices() { // Arrange - var activator = new DefaultControllerActivator(); + var activator = new DefaultControllerActivator(new DefaultTypeActivatorCache()); var serviceProvider = new Mock(MockBehavior.Strict); var testService = new TestService(); serviceProvider.Setup(s => s.GetService(typeof(TestService))) .Returns(testService) .Verifiable(); + var httpContext = new DefaultHttpContext { RequestServices = serviceProvider.Object diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerFactoryTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerFactoryTest.cs index a2051abd59..1dfc9b5272 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerFactoryTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/DefaultControllerFactoryTest.cs @@ -79,7 +79,7 @@ namespace Microsoft.AspNet.Mvc.Core RequestServices = services }; var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); - var factory = new DefaultControllerFactory(new DefaultControllerActivator()); + var factory = new DefaultControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act var result = factory.CreateController(context); @@ -105,7 +105,7 @@ namespace Microsoft.AspNet.Mvc.Core RequestServices = services }; var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); - var factory = new DefaultControllerFactory(new DefaultControllerActivator()); + var factory = new DefaultControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act var result = factory.CreateController(context); @@ -132,7 +132,7 @@ namespace Microsoft.AspNet.Mvc.Core RequestServices = services }; var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); - var factory = new DefaultControllerFactory(new DefaultControllerActivator()); + var factory = new DefaultControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act var result = factory.CreateController(context); @@ -158,7 +158,7 @@ namespace Microsoft.AspNet.Mvc.Core RequestServices = services }; var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); - var factory = new DefaultControllerFactory(new DefaultControllerActivator()); + var factory = new DefaultControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act var result = factory.CreateController(context); @@ -184,7 +184,7 @@ namespace Microsoft.AspNet.Mvc.Core RequestServices = services }; var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); - var factory = new DefaultControllerFactory(new DefaultControllerActivator()); + var factory = new DefaultControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act var result = factory.CreateController(context); @@ -208,7 +208,7 @@ namespace Microsoft.AspNet.Mvc.Core RequestServices = services }; var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); - var factory = new DefaultControllerFactory(new DefaultControllerActivator()); + var factory = new DefaultControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act var result = factory.CreateController(context); @@ -232,7 +232,7 @@ namespace Microsoft.AspNet.Mvc.Core RequestServices = services }; var context = new ActionContext(httpContext, new RouteData(), actionDescriptor); - var factory = new DefaultControllerFactory(new DefaultControllerActivator()); + var factory = new DefaultControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache())); // Act and Assert var exception = Assert.Throws(() => factory.CreateController(context)); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultModelBindersProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultModelBindersProviderTest.cs index 7b3dc21edf..82c6005224 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultModelBindersProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultModelBindersProviderTest.cs @@ -25,12 +25,14 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors var optionsAccessor = new Mock>(); optionsAccessor.SetupGet(o => o.Options) .Returns(options); - var activator = new TypeActivator(); var serviceProvider = new Mock(); serviceProvider.Setup(p => p.GetService(typeof(ITestService))) .Returns(service); + var typeActivatorCache = new DefaultTypeActivatorCache(); - var provider = new DefaultModelBindersProvider(optionsAccessor.Object, activator, serviceProvider.Object); + var provider = new DefaultModelBindersProvider(optionsAccessor.Object, + typeActivatorCache, + serviceProvider.Object); // Act var binders = provider.ModelBinders; diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValidationExcludeFiltersProviderTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValidationExcludeFiltersProviderTests.cs index c5448304f8..0c1e571d49 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValidationExcludeFiltersProviderTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValidationExcludeFiltersProviderTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.Framework.DependencyInjection; +using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.Framework.OptionsModel; using Moq; using Xunit; @@ -22,11 +22,14 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors var optionsAccessor = new Mock>(); optionsAccessor.SetupGet(o => o.Options) .Returns(options); - var activator = new TypeActivator(); + var typeActivatorCache = new Mock(); + var service = Mock.Of(); var serviceProvider = new Mock(); + serviceProvider.Setup(p => p.GetService(typeof(ITestService))) + .Returns(service); var provider = new DefaultValidationExcludeFiltersProvider(optionsAccessor.Object, - activator, - serviceProvider.Object); + typeActivatorCache.Object, + serviceProvider.Object); // Act var filters = provider.ExcludeFilters; @@ -47,11 +50,14 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors var optionsAccessor = new Mock>(); optionsAccessor.SetupGet(o => o.Options) .Returns(options); - var activator = new TypeActivator(); + var typeActivatorCache = new Mock(); + var service = Mock.Of(); var serviceProvider = new Mock(); + serviceProvider.Setup(p => p.GetService(typeof(ITestService))) + .Returns(service); var provider = new DefaultValidationExcludeFiltersProvider(optionsAccessor.Object, - activator, - serviceProvider.Object); + typeActivatorCache.Object, + serviceProvider.Object); // Act var filters = provider.ExcludeFilters; @@ -72,11 +78,14 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors var optionsAccessor = new Mock>(); optionsAccessor.SetupGet(o => o.Options) .Returns(options); - var activator = new TypeActivator(); + var typeActivatorCache = new Mock(); + var service = Mock.Of(); var serviceProvider = new Mock(); + serviceProvider.Setup(p => p.GetService(typeof(ITestService))) + .Returns(service); var provider = new DefaultValidationExcludeFiltersProvider(optionsAccessor.Object, - activator, - serviceProvider.Object); + typeActivatorCache.Object, + serviceProvider.Object); // Act var filters = provider.ExcludeFilters; @@ -98,11 +107,14 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors var optionsAccessor = new Mock>(); optionsAccessor.SetupGet(o => o.Options) .Returns(options); - var activator = new TypeActivator(); + var service = Mock.Of(); var serviceProvider = new Mock(); + serviceProvider.Setup(p => p.GetService(typeof(ITestService))) + .Returns(service); + var typeActivatorCache = new Mock(); var provider = new DefaultValidationExcludeFiltersProvider(optionsAccessor.Object, - activator, - serviceProvider.Object); + typeActivatorCache.Object, + serviceProvider.Object); // Act var filters = provider.ExcludeFilters; @@ -131,6 +143,10 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors { } } + + public interface ITestService + { + } } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValidationProviderProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValidationProviderProviderTest.cs index 52d8b702b7..af31c9f994 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValidationProviderProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValidationProviderProviderTest.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using Microsoft.AspNet.Mvc.ModelBinding; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; using Moq; using Xunit; @@ -20,10 +19,10 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors var service = Mock.Of(); var validationProvider = Mock.Of(); var type = typeof(TestModelValidationProvider); - var typeActivator = new TypeActivator(); var serviceProvider = new Mock(); serviceProvider.Setup(p => p.GetService(typeof(ITestService))) .Returns(service); + var typeActivatorCache = new DefaultTypeActivatorCache(); var options = new MvcOptions(); options.ModelValidatorProviders.Add(type); options.ModelValidatorProviders.Add(validationProvider); @@ -31,7 +30,7 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors accessor.SetupGet(a => a.Options) .Returns(options); var provider = new DefaultModelValidatorProviderProvider(accessor.Object, - typeActivator, + typeActivatorCache, serviceProvider.Object); // Act diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValueProviderFactoryProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValueProviderFactoryProviderTest.cs index eb24f18b62..f5d0f76b53 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValueProviderFactoryProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultValueProviderFactoryProviderTest.cs @@ -3,7 +3,6 @@ using System; using Microsoft.AspNet.Mvc.ModelBinding; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; using Moq; using Xunit; @@ -19,10 +18,10 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors var service = Mock.Of(); var valueProviderFactory = Mock.Of(); var type = typeof(TestValueProviderFactory); - var typeActivator = new TypeActivator(); var serviceProvider = new Mock(); serviceProvider.Setup(p => p.GetService(typeof(ITestService))) .Returns(service); + var typeActivatorCache = new DefaultTypeActivatorCache(); var options = new MvcOptions(); options.ValueProviderFactories.Add(valueProviderFactory); options.ValueProviderFactories.Add(type); @@ -30,7 +29,7 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors accessor.SetupGet(a => a.Options) .Returns(options); var provider = new DefaultValueProviderFactoryProvider(accessor.Object, - typeActivator, + typeActivatorCache, serviceProvider.Object); // Act diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultViewEngineProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultViewEngineProviderTest.cs index 43df2a8e2c..f77c05f683 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultViewEngineProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/OptionDescriptors/DefaultViewEngineProviderTest.cs @@ -3,7 +3,6 @@ using System; using Microsoft.AspNet.Mvc.Rendering; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.OptionsModel; using Moq; using Xunit; @@ -19,17 +18,17 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors var service = Mock.Of(); var viewEngine = Mock.Of(); var type = typeof(TestViewEngine); - var typeActivator = new TypeActivator(); var serviceProvider = new Mock(); serviceProvider.Setup(p => p.GetService(typeof(ITestService))) .Returns(service); + var typeActivatorCache = new DefaultTypeActivatorCache(); var options = new MvcOptions(); options.ViewEngines.Add(viewEngine); options.ViewEngines.Add(type); var accessor = new Mock>(); accessor.SetupGet(a => a.Options) .Returns(options); - var provider = new DefaultViewEngineProvider(accessor.Object, typeActivator, serviceProvider.Object); + var provider = new DefaultViewEngineProvider(accessor.Object, typeActivatorCache, serviceProvider.Object); // Act var result = provider.ViewEngines; diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/BindAttributeTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/BindAttributeTest.cs index 273333733f..51a21f90b7 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/BindAttributeTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/BindAttributeTest.cs @@ -74,18 +74,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { HttpContext = new DefaultHttpContext(), }; - - var activator = new Mock(MockBehavior.Strict); - activator - .Setup(a => a.CreateInstance(It.IsAny(), typeof(TestProvider), It.IsAny())) - .Returns(new TestProvider()) - .Verifiable(); - - var services = new Mock(MockBehavior.Strict); - services - .Setup(s => s.GetService(typeof(ITypeActivator))) - .Returns(activator.Object); - + var services = new Mock(); + context.OperationBindingContext.HttpContext.RequestServices = services.Object; // Act @@ -109,17 +99,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding HttpContext = new DefaultHttpContext(), }; - var activator = new Mock(MockBehavior.Strict); - activator - .Setup(a => a.CreateInstance(It.IsAny(), typeof(TestProvider), It.IsAny())) - .Returns(new TestProvider()) - .Verifiable(); - var services = new Mock(MockBehavior.Strict); - services - .Setup(s => s.GetService(typeof(ITypeActivator))) - .Returns(activator.Object); - + context.OperationBindingContext.HttpContext.RequestServices = services.Object; // Act @@ -128,11 +109,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // Assert Assert.True(predicate(context, "UserName")); Assert.True(predicate(context, "UserName")); - - activator - .Verify( - a => a.CreateInstance(It.IsAny(), typeof(TestProvider), It.IsAny()), - Times.Once()); } #endif diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/BinderTypeBasedModelBinderModelBinderTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/BinderTypeBasedModelBinderModelBinderTest.cs index 0be2a2f81f..1dcdd9c66e 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/BinderTypeBasedModelBinderModelBinderTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/BinderTypeBasedModelBinderModelBinderTest.cs @@ -6,9 +6,10 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNet.Http.Core; -using Microsoft.Framework.DependencyInjection; using Moq; using Xunit; +using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.DependencyInjection.Fallback; namespace Microsoft.AspNet.Mvc.ModelBinding.Test { @@ -20,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test // Arrange var bindingContext = GetBindingContext(typeof(Person)); - var binder = new BinderTypeBasedModelBinder(Mock.Of()); + var binder = new BinderTypeBasedModelBinder(); // Act var binderResult = await binder.BindModelAsync(bindingContext); @@ -36,14 +37,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test var bindingContext = GetBindingContext(typeof(Person)); bindingContext.ModelMetadata.BinderType = typeof(FalseModelBinder); - var innerModelBinder = new FalseModelBinder(); - - var mockITypeActivator = new Mock(); - mockITypeActivator - .Setup(o => o.CreateInstance(It.IsAny(), typeof(FalseModelBinder))) - .Returns(innerModelBinder); - - var binder = new BinderTypeBasedModelBinder(mockITypeActivator.Object); + var binder = new BinderTypeBasedModelBinder(); // Act var binderResult = await binder.BindModelAsync(bindingContext); @@ -60,21 +54,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test bindingContext.ModelMetadata.BinderType = typeof(TrueModelBinder); var model = new Person(); - var innerModelBinder = new TrueModelBinder(model); + var innerModelBinder = new TrueModelBinder(); + var serviceProvider = new ServiceCollection() + .AddSingleton(typeof(IModelBinder)) + .BuildServiceProvider(); - var mockITypeActivator = new Mock(); - mockITypeActivator - .Setup(o => o.CreateInstance(It.IsAny(), typeof(TrueModelBinder))) - .Returns(innerModelBinder); + bindingContext.OperationBindingContext.HttpContext.RequestServices = serviceProvider; - var binder = new BinderTypeBasedModelBinder(mockITypeActivator.Object); + var binder = new BinderTypeBasedModelBinder(); // Act var binderResult = await binder.BindModelAsync(bindingContext); // Assert + var p = (Person)bindingContext.Model; Assert.True(binderResult); - Assert.Same(model, bindingContext.Model); + Assert.Equal(model.Age, p.Age); + Assert.Equal(model.Name, p.Name); } [Fact] @@ -85,23 +81,24 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test bindingContext.ModelMetadata.BinderType = typeof(ModelBinderProvider); var model = new Person(); - var innerModelBinder = new TrueModelBinder(model); + var provider = new ModelBinderProvider(); - var provider = new ModelBinderProvider(innerModelBinder); + var serviceProvider = new ServiceCollection() + .AddSingleton(typeof(IModelBinderProvider)) + .AddSingleton(typeof(IModelBinder)) + .BuildServiceProvider(); - var mockITypeActivator = new Mock(); - mockITypeActivator - .Setup(o => o.CreateInstance(It.IsAny(), typeof(ModelBinderProvider))) - .Returns(provider); - - var binder = new BinderTypeBasedModelBinder(mockITypeActivator.Object); + bindingContext.OperationBindingContext.HttpContext.RequestServices = serviceProvider; + var binder = new BinderTypeBasedModelBinder(); // Act var binderResult = await binder.BindModelAsync(bindingContext); // Assert + var p = (Person)bindingContext.Model; Assert.True(binderResult); - Assert.Same(model, bindingContext.Model); + Assert.Equal(model.Age, p.Age); + Assert.Equal(model.Name, p.Name); } [Fact] @@ -109,10 +106,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test { // Arrange var bindingContext = GetBindingContext(typeof(Person)); - bindingContext.ModelMetadata.BinderType = typeof(string); - var binder = new BinderTypeBasedModelBinder(Mock.Of()); + bindingContext.ModelMetadata.BinderType = typeof(Person); + var binder = new BinderTypeBasedModelBinder(); - var expected = "The type 'System.String' must implement either " + + var expected = "The type '" + typeof(Person).FullName + "' must implement either " + "'Microsoft.AspNet.Mvc.ModelBinding.IModelBinder' or " + "'Microsoft.AspNet.Mvc.ModelBinding.IModelBinderProvider' to be used as a model binder."; @@ -165,9 +162,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test { private readonly object _model; - public TrueModelBinder(object model) + public TrueModelBinder() { - _model = model; + _model = new Person(); } public Task BindModelAsync(ModelBindingContext bindingContext) @@ -181,9 +178,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test { private readonly IModelBinder _inner; - public ModelBinderProvider(IModelBinder inner) + public ModelBinderProvider() { - _inner = inner; + var innerModelBinder = new TrueModelBinder(); + _inner = innerModelBinder; } public IReadOnlyList ModelBinders diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/CompositeModelBinderTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/CompositeModelBinderTest.cs index 4a69e3b988..e1f2ef22ff 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/CompositeModelBinderTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/CompositeModelBinderTest.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -using Microsoft.Framework.DependencyInjection; using Moq; using Xunit; @@ -420,16 +419,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test private static CompositeModelBinder CreateBinderWithDefaults() { - var serviceProvider = Mock.Of(); - var typeActivator = new Mock(); - typeActivator - .Setup(t => t.CreateInstance(serviceProvider, It.IsAny(), It.IsAny())) - .Returns((IServiceProvider sp, Type t, object[] args) => Activator.CreateInstance(t)); var binders = new IModelBinder[] { new TypeMatchModelBinder(), new ByteArrayModelBinder(), - new GenericModelBinder(serviceProvider, typeActivator.Object), + new GenericModelBinder(), new ComplexModelDtoModelBinder(), new TypeConverterModelBinder(), new MutableObjectModelBinder() diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/MutableObjectModelBinderTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/MutableObjectModelBinderTest.cs index a2cfb48043..1801c8ae5a 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/MutableObjectModelBinderTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/MutableObjectModelBinderTest.cs @@ -11,7 +11,6 @@ using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNet.Http.Core; using Microsoft.AspNet.Testing; -using Microsoft.Framework.DependencyInjection; using Moq; using Xunit; @@ -1572,16 +1571,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding private IServiceProvider CreateServices() { var services = new Mock(MockBehavior.Strict); - - var typeActivator = new Mock(MockBehavior.Strict); - typeActivator - .Setup(f => f.CreateInstance(It.IsAny(), typeof(ExcludedProvider))) - .Returns(new ExcludedProvider()); - - services - .Setup(s => s.GetService(typeof(ITypeActivator))) - .Returns(typeActivator.Object); - return services.Object; } diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/OptionDescriptors/DefaultViewLocationExpanderProviderTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/OptionDescriptors/DefaultViewLocationExpanderProviderTest.cs index 6ed5fec52e..495fdc0992 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/OptionDescriptors/DefaultViewLocationExpanderProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/OptionDescriptors/DefaultViewLocationExpanderProviderTest.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; -using Microsoft.Framework.DependencyInjection; +using Microsoft.AspNet.Mvc.OptionDescriptors; using Microsoft.Framework.OptionsModel; using Moq; using Xunit; @@ -19,10 +19,10 @@ namespace Microsoft.AspNet.Mvc.Razor.OptionDescriptors var service = Mock.Of(); var expander = Mock.Of(); var type = typeof(TestViewLocationExpander); - var typeActivator = new TypeActivator(); var serviceProvider = new Mock(); serviceProvider.Setup(p => p.GetService(typeof(ITestService))) .Returns(service); + var typeActivatorCache = new DefaultTypeActivatorCache(); var options = new RazorViewEngineOptions(); options.ViewLocationExpanders.Add(type); options.ViewLocationExpanders.Add(expander); @@ -30,7 +30,7 @@ namespace Microsoft.AspNet.Mvc.Razor.OptionDescriptors accessor.SetupGet(a => a.Options) .Returns(options); var provider = new DefaultViewLocationExpanderProvider(accessor.Object, - typeActivator, + typeActivatorCache, serviceProvider.Object); // Act diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageActivatorTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageActivatorTest.cs index a2c9d81ce6..e5c2793e19 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageActivatorTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageActivatorTest.cs @@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.Razor public void Activate_ActivatesAndContextualizesPropertiesOnViews() { // Arrange - var activator = new RazorPageActivator(Mock.Of()); + var activator = new RazorPageActivator(new EmptyModelMetadataProvider()); var instance = new TestRazorPage(); var myService = new MyService(); @@ -55,7 +55,7 @@ namespace Microsoft.AspNet.Mvc.Razor public void Activate_ThrowsIfTheViewDoesNotDeriveFromRazorViewOfT() { // Arrange - var activator = new RazorPageActivator(Mock.Of()); + var activator = new RazorPageActivator(new EmptyModelMetadataProvider()); var instance = new DoesNotDeriveFromRazorPageOfT(); var myService = new MyService(); @@ -85,8 +85,7 @@ namespace Microsoft.AspNet.Mvc.Razor public void Activate_InstantiatesNewViewDataDictionaryType_IfTheTypeDoesNotMatch() { // Arrange - var typeActivator = new TypeActivator(); - var activator = new RazorPageActivator(typeActivator); + var activator = new RazorPageActivator(new EmptyModelMetadataProvider()); var instance = new TestRazorPage(); var myService = new MyService(); @@ -121,8 +120,7 @@ namespace Microsoft.AspNet.Mvc.Razor public void Activate_UsesPassedInViewDataDictionaryInstance_IfPassedInTypeMatches() { // Arrange - var typeActivator = new TypeActivator(); - var activator = new RazorPageActivator(typeActivator); + var activator = new RazorPageActivator(new EmptyModelMetadataProvider()); var instance = new TestRazorPage(); var myService = new MyService(); var helper = Mock.Of>(); @@ -156,8 +154,7 @@ namespace Microsoft.AspNet.Mvc.Razor public void Activate_DeterminesModelTypeFromProperty() { // Arrange - var typeActivator = new TypeActivator(); - var activator = new RazorPageActivator(typeActivator); + var activator = new RazorPageActivator(new EmptyModelMetadataProvider()); var instance = new DoesNotDeriveFromRazorPageOfTButHasModelProperty(); var myService = new MyService(); var helper = Mock.Of>(); diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageCreateTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageCreateTagHelperTest.cs index f56db5aa50..29edf2a2b0 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageCreateTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageCreateTagHelperTest.cs @@ -72,14 +72,11 @@ namespace Microsoft.AspNet.Mvc.Razor private static TestRazorPage CreateTestRazorPage() { - var typeActivator = new TypeActivator(); - var activator = new RazorPageActivator(typeActivator); + var activator = new RazorPageActivator(new EmptyModelMetadataProvider()); var serviceProvider = new Mock(); var myService = new MyService(); serviceProvider.Setup(mock => mock.GetService(typeof(MyService))) .Returns(myService); - serviceProvider.Setup(mock => mock.GetService(typeof(ITypeActivator))) - .Returns(typeActivator); serviceProvider.Setup(mock => mock.GetService(typeof(ITagHelperActivator))) .Returns(new DefaultTagHelperActivator()); var httpContext = new Mock(); diff --git a/test/WebSites/RequestServicesWebSite/RequestScopedActionConstraint.cs b/test/WebSites/RequestServicesWebSite/RequestScopedActionConstraint.cs index ef9e373af8..54b9224a1f 100644 --- a/test/WebSites/RequestServicesWebSite/RequestScopedActionConstraint.cs +++ b/test/WebSites/RequestServicesWebSite/RequestScopedActionConstraint.cs @@ -2,6 +2,7 @@ // 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 Microsoft.AspNet.Mvc; using Microsoft.Framework.DependencyInjection; @@ -11,6 +12,10 @@ namespace RequestServicesWebSite public class RequestScopedActionConstraintAttribute : Attribute, IActionConstraintFactory { private readonly string _requestId; + private readonly Func CreateFactory = + (t, s) => ActivatorUtilities.CreateFactory(t, new[] { s.GetType() }); + private readonly ConcurrentDictionary _constraintCache = + new ConcurrentDictionary(); public RequestScopedActionConstraintAttribute(string requestId) { @@ -19,8 +24,8 @@ namespace RequestServicesWebSite public IActionConstraint CreateInstance(IServiceProvider services) { - var activator = services.GetService(); - return activator.CreateInstance(services, _requestId); + var constraintType = typeof(Constraint); + return (Constraint)ActivatorUtilities.CreateInstance(services, typeof(Constraint),new[] { _requestId }); } private class Constraint : IActionConstraint