Cleanup services

Explicitly register nestedprovider managers
Make IActionSelector singleton
This commit is contained in:
Yishai Galatzer 2015-02-19 11:10:45 -08:00
parent cf80721994
commit b12c4c5ef8
5 changed files with 45 additions and 34 deletions

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
@ -16,13 +17,17 @@ namespace Microsoft.AspNet.Mvc
/// <param name="action">The <see cref="ActionDescriptor"/> for which constraints are being created.</param> /// <param name="action">The <see cref="ActionDescriptor"/> for which constraints are being created.</param>
/// <param name="items">The list of <see cref="ActionConstraintItem"/> objects.</param> /// <param name="items">The list of <see cref="ActionConstraintItem"/> objects.</param>
public ActionConstraintProviderContext( public ActionConstraintProviderContext(
[NotNull] HttpContext context,
[NotNull] ActionDescriptor action, [NotNull] ActionDescriptor action,
[NotNull] IList<ActionConstraintItem> items) [NotNull] IList<ActionConstraintItem> items)
{ {
HttpContext = context;
Action = action; Action = action;
Results = items; Results = items;
} }
public HttpContext HttpContext { get; }
/// <summary> /// <summary>
/// The <see cref="ActionDescriptor"/> for which constraints are being created. /// The <see cref="ActionDescriptor"/> for which constraints are being created.
/// </summary> /// </summary>

View File

@ -16,17 +16,6 @@ namespace Microsoft.AspNet.Mvc
/// </remarks> /// </remarks>
public class DefaultActionConstraintProvider : INestedProvider<ActionConstraintProviderContext> public class DefaultActionConstraintProvider : INestedProvider<ActionConstraintProviderContext>
{ {
private readonly IServiceProvider _services;
/// <summary>
/// Creates a new <see cref="DefaultActionConstraintProvider"/>.
/// </summary>
/// <param name="services">The per-request services.</param>
public DefaultActionConstraintProvider(IServiceProvider services)
{
_services = services;
}
/// <inheritdoc /> /// <inheritdoc />
public int Order public int Order
{ {
@ -38,13 +27,13 @@ namespace Microsoft.AspNet.Mvc
{ {
foreach (var item in context.Results) foreach (var item in context.Results)
{ {
ProvideConstraint(item); ProvideConstraint(item, context.HttpContext.RequestServices);
} }
callNext(); callNext();
} }
private void ProvideConstraint(ActionConstraintItem item) private void ProvideConstraint(ActionConstraintItem item, IServiceProvider services)
{ {
// Don't overwrite anything that was done by a previous provider. // Don't overwrite anything that was done by a previous provider.
if (item.Constraint != null) if (item.Constraint != null)
@ -62,7 +51,7 @@ namespace Microsoft.AspNet.Mvc
var factory = item.Metadata as IActionConstraintFactory; var factory = item.Metadata as IActionConstraintFactory;
if (factory != null) if (factory != null)
{ {
item.Constraint = factory.CreateInstance(_services); item.Constraint = factory.CreateInstance(services);
return; return;
} }
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Logging; using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.Routing; using Microsoft.AspNet.Mvc.Routing;
@ -43,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
var candidates = new List<ActionSelectorCandidate>(); var candidates = new List<ActionSelectorCandidate>();
foreach (var action in matchingRouteConstraints) foreach (var action in matchingRouteConstraints)
{ {
var constraints = GetConstraints(action); var constraints = GetConstraints(context.HttpContext, action);
candidates.Add(new ActionSelectorCandidate(action, constraints)); candidates.Add(new ActionSelectorCandidate(action, constraints));
} }
@ -253,7 +254,7 @@ namespace Microsoft.AspNet.Mvc
return descriptors.Items; return descriptors.Items;
} }
private IReadOnlyList<IActionConstraint> GetConstraints(ActionDescriptor action) private IReadOnlyList<IActionConstraint> GetConstraints(HttpContext httpContext, ActionDescriptor action)
{ {
if (action.ActionConstraints == null || action.ActionConstraints.Count == 0) if (action.ActionConstraints == null || action.ActionConstraints.Count == 0)
{ {
@ -261,7 +262,7 @@ namespace Microsoft.AspNet.Mvc
} }
var items = action.ActionConstraints.Select(c => new ActionConstraintItem(c)).ToList(); var items = action.ActionConstraints.Select(c => new ActionConstraintItem(c)).ToList();
var context = new ActionConstraintProviderContext(action, items); var context = new ActionConstraintProviderContext(httpContext, action, items);
_actionConstraintProvider.Invoke(context); _actionConstraintProvider.Invoke(context);

View File

@ -23,22 +23,24 @@ namespace Microsoft.AspNet.Mvc
{ {
public class MvcServices public class MvcServices
{ {
public static IEnumerable<IServiceDescriptor> GetDefaultServices(IConfiguration configuration = null) public static IEnumerable<IServiceDescriptor> GetDefaultServices()
{
return GetDefaultServices(null);
}
public static IEnumerable<IServiceDescriptor> GetDefaultServices(IConfiguration configuration)
{ {
var describe = new ServiceDescriber(configuration); var describe = new ServiceDescriber(configuration);
// Options and core services. // Options and core services.
yield return describe.Transient<IConfigureOptions<MvcOptions>, MvcOptionsSetup>(); yield return describe.Transient<IConfigureOptions<MvcOptions>, MvcOptionsSetup>();
yield return describe.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>(); yield return describe.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>();
yield return describe.Transient<IAssemblyProvider, DefaultAssemblyProvider>(); yield return describe.Transient<IAssemblyProvider, DefaultAssemblyProvider>();
yield return describe.Transient(typeof(INestedProviderManager<>), typeof(NestedProviderManager<>));
yield return describe.Transient(
typeof(INestedProviderManagerAsync<>),
typeof(NestedProviderManagerAsync<>));
yield return describe.Transient<MvcMarkerService, MvcMarkerService>(); yield return describe.Transient<MvcMarkerService, MvcMarkerService>();
yield return describe.Singleton(typeof(ITypeActivatorCache), typeof(DefaultTypeActivatorCache)); yield return describe.Singleton(typeof(ITypeActivatorCache), typeof(DefaultTypeActivatorCache));
yield return describe.Scoped(typeof(IScopedInstance<>), typeof(ScopedInstance<>)); yield return describe.Scoped(typeof(IScopedInstance<>), typeof(ScopedInstance<>));
// Core action discovery, filters and action execution. // Core action discovery, filters and action execution.
// These are consumed only when creating action descriptors, then they can be de-allocated // These are consumed only when creating action descriptors, then they can be de-allocated
@ -56,25 +58,34 @@ namespace Microsoft.AspNet.Mvc
// This provider needs access to the per-request services, but might be used many times for a given // This provider needs access to the per-request services, but might be used many times for a given
// request. // request.
yield return describe.Scoped<INestedProvider<ActionConstraintProviderContext>, yield return describe.Transient<INestedProviderManager<ActionConstraintProviderContext>,
NestedProviderManager<ActionConstraintProviderContext>>();
yield return describe.Transient<INestedProvider<ActionConstraintProviderContext>,
DefaultActionConstraintProvider>(); DefaultActionConstraintProvider>();
yield return describe.Singleton<IActionSelectorDecisionTreeProvider, ActionSelectorDecisionTreeProvider>(); yield return describe.Singleton<IActionSelectorDecisionTreeProvider, ActionSelectorDecisionTreeProvider>();
yield return describe.Scoped<IActionSelector, DefaultActionSelector>(); yield return describe.Singleton<IActionSelector, DefaultActionSelector>();
yield return describe.Transient<IControllerActionArgumentBinder, DefaultControllerActionArgumentBinder>(); yield return describe.Transient<IControllerActionArgumentBinder, DefaultControllerActionArgumentBinder>();
yield return describe.Transient<IObjectModelValidator, DefaultObjectValidator>(); yield return describe.Transient<IObjectModelValidator, DefaultObjectValidator>();
yield return describe.Transient<INestedProviderManager<ActionDescriptorProviderContext>,
NestedProviderManager<ActionDescriptorProviderContext>>();
yield return describe.Transient<INestedProvider<ActionDescriptorProviderContext>, yield return describe.Transient<INestedProvider<ActionDescriptorProviderContext>,
ControllerActionDescriptorProvider>(); ControllerActionDescriptorProvider>();
yield return describe.Transient<INestedProviderManager<ActionInvokerProviderContext>,
NestedProviderManager<ActionInvokerProviderContext>>();
yield return describe.Transient<INestedProvider<ActionInvokerProviderContext>, yield return describe.Transient<INestedProvider<ActionInvokerProviderContext>,
ControllerActionInvokerProvider>(); ControllerActionInvokerProvider>();
yield return describe.Singleton<IActionDescriptorsCollectionProvider, yield return describe.Singleton<IActionDescriptorsCollectionProvider,
DefaultActionDescriptorsCollectionProvider>(); DefaultActionDescriptorsCollectionProvider>();
// The IGlobalFilterProvider is used to build the action descriptors (likely once) and so should // The IGlobalFilterProvider is used to build the action descriptors (likely once) and so should
// remain transient to avoid keeping it in memory. // remain transient to avoid keeping it in memory.
yield return describe.Transient<IGlobalFilterProvider, DefaultGlobalFilterProvider>(); yield return describe.Transient<IGlobalFilterProvider, DefaultGlobalFilterProvider>();
yield return describe.Transient<INestedProviderManager<FilterProviderContext>,
NestedProviderManager<FilterProviderContext>>();
yield return describe.Transient<INestedProvider<FilterProviderContext>, DefaultFilterProvider>(); yield return describe.Transient<INestedProvider<FilterProviderContext>, DefaultFilterProvider>();
yield return describe.Transient<FormatFilter, FormatFilter>(); yield return describe.Transient<FormatFilter, FormatFilter>();
@ -89,7 +100,7 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Transient<IModelBinderProvider, DefaultModelBindersProvider>(); yield return describe.Transient<IModelBinderProvider, DefaultModelBindersProvider>();
yield return describe.Transient<IValueProviderFactoryProvider, DefaultValueProviderFactoryProvider>(); yield return describe.Transient<IValueProviderFactoryProvider, DefaultValueProviderFactoryProvider>();
yield return describe.Transient<IOutputFormattersProvider, DefaultOutputFormattersProvider>(); yield return describe.Transient<IOutputFormattersProvider, DefaultOutputFormattersProvider>();
yield return describe.Instance<JsonOutputFormatter>(new JsonOutputFormatter()); yield return describe.Instance(new JsonOutputFormatter());
yield return describe.Transient<IModelValidatorProviderProvider, DefaultModelValidatorProviderProvider>(); yield return describe.Transient<IModelValidatorProviderProvider, DefaultModelValidatorProviderProvider>();
yield return describe.Transient<IValidationExcludeFiltersProvider, yield return describe.Transient<IValidationExcludeFiltersProvider,
@ -130,11 +141,11 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Scoped<IViewStartProvider, ViewStartProvider>(); yield return describe.Scoped<IViewStartProvider, ViewStartProvider>();
yield return describe.Transient<IRazorViewFactory, RazorViewFactory>(); yield return describe.Transient<IRazorViewFactory, RazorViewFactory>();
yield return describe.Singleton<IRazorPageActivator, RazorPageActivator>(); yield return describe.Singleton<IRazorPageActivator, RazorPageActivator>();
// Virtual path view factory needs to stay scoped so views can get get scoped services. // Virtual path view factory needs to stay scoped so views can get get scoped services.
yield return describe.Scoped<IRazorPageFactory, VirtualPathRazorPageFactory>(); yield return describe.Scoped<IRazorPageFactory, VirtualPathRazorPageFactory>();
// View and rendering helpers // View and rendering helpers
yield return describe.Transient<IHtmlHelper, HtmlHelper>(); yield return describe.Transient<IHtmlHelper, HtmlHelper>();
yield return describe.Transient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>)); yield return describe.Transient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>));
yield return describe.Scoped<IUrlHelper, UrlHelper>(); yield return describe.Scoped<IUrlHelper, UrlHelper>();
@ -152,19 +163,21 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Transient<IViewComponentSelector, DefaultViewComponentSelector>(); yield return describe.Transient<IViewComponentSelector, DefaultViewComponentSelector>();
yield return describe.Singleton<IViewComponentActivator, DefaultViewComponentActivator>(); yield return describe.Singleton<IViewComponentActivator, DefaultViewComponentActivator>();
yield return describe.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>(); yield return describe.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>();
yield return describe.Transient<INestedProviderManager<ViewComponentInvokerProviderContext>,
NestedProviderManager<ViewComponentInvokerProviderContext>>();
yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>, yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>,
DefaultViewComponentInvokerProvider>(); DefaultViewComponentInvokerProvider>();
yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>(); yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>();
// Security and Authorization // Security and Authorization
yield return describe.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>(); yield return describe.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>();
yield return describe.Singleton<AntiForgery, AntiForgery>(); yield return describe.Singleton<AntiForgery, AntiForgery>();
yield return describe.Singleton<IAntiForgeryAdditionalDataProvider, yield return describe.Singleton<IAntiForgeryAdditionalDataProvider,
DefaultAntiForgeryAdditionalDataProvider>(); DefaultAntiForgeryAdditionalDataProvider>();
// Api Description // Api Description
yield return describe.Transient<INestedProviderManager<ApiDescriptionProviderContext>,
NestedProviderManager<ApiDescriptionProviderContext>>();
yield return describe.Singleton<IApiDescriptionGroupCollectionProvider, yield return describe.Singleton<IApiDescriptionGroupCollectionProvider,
ApiDescriptionGroupCollectionProvider>(); ApiDescriptionGroupCollectionProvider>();
yield return describe.Transient<INestedProvider<ApiDescriptionProviderContext>, yield return describe.Transient<INestedProvider<ApiDescriptionProviderContext>,

View File

@ -745,7 +745,7 @@ namespace Microsoft.AspNet.Mvc
var actionConstraintProvider = new NestedProviderManager<ActionConstraintProviderContext>( var actionConstraintProvider = new NestedProviderManager<ActionConstraintProviderContext>(
new INestedProvider<ActionConstraintProviderContext>[] new INestedProvider<ActionConstraintProviderContext>[]
{ {
new DefaultActionConstraintProvider(serviceContainer), new DefaultActionConstraintProvider(),
}); });
var defaultActionSelector = new DefaultActionSelector( var defaultActionSelector = new DefaultActionSelector(
@ -831,7 +831,7 @@ namespace Microsoft.AspNet.Mvc
var actionConstraintProvider = new NestedProviderManager<ActionConstraintProviderContext>( var actionConstraintProvider = new NestedProviderManager<ActionConstraintProviderContext>(
new INestedProvider<ActionConstraintProviderContext>[] new INestedProvider<ActionConstraintProviderContext>[]
{ {
new DefaultActionConstraintProvider(new ServiceContainer()), new DefaultActionConstraintProvider(),
new BooleanConstraintProvider(), new BooleanConstraintProvider(),
}); });
@ -860,14 +860,17 @@ namespace Microsoft.AspNet.Mvc
var routeData = new RouteData(); var routeData = new RouteData();
routeData.Routers.Add(new Mock<IRouter>(MockBehavior.Strict).Object); routeData.Routers.Add(new Mock<IRouter>(MockBehavior.Strict).Object);
var serviceContainer = new ServiceContainer();
var httpContext = new Mock<HttpContext>(MockBehavior.Strict); var httpContext = new Mock<HttpContext>(MockBehavior.Strict);
var request = new Mock<HttpRequest>(MockBehavior.Strict); var request = new Mock<HttpRequest>(MockBehavior.Strict);
httpContext.SetupGet(c => c.Request).Returns(request.Object);
request.SetupGet(r => r.Method).Returns(httpMethod); request.SetupGet(r => r.Method).Returns(httpMethod);
request.SetupGet(r => r.Path).Returns(new PathString()); request.SetupGet(r => r.Path).Returns(new PathString());
httpContext.SetupGet(c => c.Request).Returns(request.Object);
httpContext.SetupGet(c => c.RequestServices).Returns(serviceContainer);
return new RouteContext(httpContext.Object) return new RouteContext(httpContext.Object)
{ {
RouteData = routeData, RouteData = routeData,