Permalink
Browse files

Commonize code from ControllerActionInvokerCache and PageFilterFactor…

…yProvider
  • Loading branch information...
1 parent 9cc20ff commit 6b0282fa84c546cf1d1b1e7bf2c707e076b4326f @pranavkm pranavkm committed Dec 30, 2016
@@ -44,112 +44,32 @@ private InnerCache CurrentCache
public ControllerActionInvokerState GetState(ControllerContext controllerContext)
{
- // Filter instances from statically defined filter descriptors + from filter providers
- IFilterMetadata[] filters;
-
var cache = CurrentCache;
var actionDescriptor = controllerContext.ActionDescriptor;
+ IFilterMetadata[] filters;
Entry cacheEntry;
- if (cache.Entries.TryGetValue(actionDescriptor, out cacheEntry))
+ if (!cache.Entries.TryGetValue(actionDescriptor, out cacheEntry))
{
- // Deep copy the cached filter items as filter providers could modify them
- var filterItems = new List<FilterItem>(cacheEntry.FilterItems.Count);
- for (var i = 0; i < cacheEntry.FilterItems.Count; i++)
- {
- var filterItem = cacheEntry.FilterItems[i];
- filterItems.Add(
- new FilterItem(filterItem.Descriptor)
- {
- Filter = filterItem.Filter,
- IsReusable = filterItem.IsReusable
- });
- }
+ var filterFactoryResult = FilterFactory.GetAllFilters(_filterProviders, controllerContext);
+ filters = filterFactoryResult.Filters;
- filters = GetFilters(controllerContext, filterItems);
+ var executor = ObjectMethodExecutor.Create(
+ actionDescriptor.MethodInfo,
+ actionDescriptor.ControllerTypeInfo);
- return new ControllerActionInvokerState(filters, cacheEntry.ActionMethodExecutor);
+ cacheEntry = new Entry(filterFactoryResult.CacheableFilters, executor);
+ cacheEntry = cache.Entries.GetOrAdd(actionDescriptor, cacheEntry);
}
-
- var executor = ObjectMethodExecutor.Create(
- actionDescriptor.MethodInfo,
- actionDescriptor.ControllerTypeInfo);
-
- var staticFilterItems = new List<FilterItem>(actionDescriptor.FilterDescriptors.Count);
- for (var i = 0; i < actionDescriptor.FilterDescriptors.Count; i++)
- {
- staticFilterItems.Add(new FilterItem(actionDescriptor.FilterDescriptors[i]));
- }
-
- // Create a separate collection as we want to hold onto the statically defined filter items
- // in order to cache them
- var allFilterItems = new List<FilterItem>(staticFilterItems);
-
- filters = GetFilters(controllerContext, allFilterItems);
-
- // Cache the filter items based on the following criteria
- // 1. Are created statically (ex: via filter attributes, added to global filter list etc.)
- // 2. Are re-usable
- for (var i = 0; i < staticFilterItems.Count; i++)
+ else
{
- var item = staticFilterItems[i];
- if (!item.IsReusable)
- {
- item.Filter = null;
- }
+ // Filter instances from statically defined filter descriptors + from filter providers
+ filters = FilterFactory.CreateUncachedFilters(_filterProviders, controllerContext, cacheEntry.FilterItems);
}
- cacheEntry = new Entry(staticFilterItems, executor);
- cache.Entries.TryAdd(actionDescriptor, cacheEntry);
return new ControllerActionInvokerState(filters, cacheEntry.ActionMethodExecutor);
}
- private IFilterMetadata[] GetFilters(ActionContext actionContext, List<FilterItem> filterItems)
- {
- // Execute providers
- var context = new FilterProviderContext(actionContext, filterItems);
-
- for (var i = 0; i < _filterProviders.Length; i++)
- {
- _filterProviders[i].OnProvidersExecuting(context);
- }
-
- for (var i = _filterProviders.Length - 1; i >= 0; i--)
- {
- _filterProviders[i].OnProvidersExecuted(context);
- }
-
- // Extract filter instances from statically defined filters and filter providers
- var count = 0;
- for (var i = 0; i < filterItems.Count; i++)
- {
- if (filterItems[i].Filter != null)
- {
- count++;
- }
- }
-
- if (count == 0)
- {
- return EmptyArray<IFilterMetadata>.Instance;
- }
- else
- {
- var filters = new IFilterMetadata[count];
- var filterIndex = 0;
- for (int i = 0; i < filterItems.Count; i++)
- {
- var filter = filterItems[i].Filter;
- if (filter != null)
- {
- filters[filterIndex++] = filter;
- }
- }
-
- return filters;
- }
- }
-
private class InnerCache
{
public InnerCache(int version)
@@ -165,13 +85,13 @@ public InnerCache(int version)
private struct Entry
{
- public Entry(List<FilterItem> items, ObjectMethodExecutor executor)
+ public Entry(FilterItem[] items, ObjectMethodExecutor executor)
{
FilterItems = items;
ActionMethodExecutor = executor;
}
- public List<FilterItem> FilterItems { get; }
+ public FilterItem[] FilterItems { get; }
public ObjectMethodExecutor ActionMethodExecutor { get; }
}
@@ -0,0 +1,139 @@
+// 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.Generic;
+using Microsoft.AspNetCore.Mvc.Filters;
+
+namespace Microsoft.AspNetCore.Mvc.Internal
+{
+ public static class FilterFactory
+ {
+ public static FilterFactoryResult GetAllFilters(
+ IFilterProvider[] filterProviders,
+ ActionContext actionContext)
+ {
+ if (filterProviders == null)
+ {
+ throw new ArgumentNullException(nameof(filterProviders));
+ }
+
+ if (actionContext == null)
+ {
+ throw new ArgumentNullException(nameof(actionContext));
+ }
+
+ var actionDescriptor = actionContext.ActionDescriptor;
+
+ var staticFilterItems = new FilterItem[actionDescriptor.FilterDescriptors.Count];
+ for (var i = 0; i < actionDescriptor.FilterDescriptors.Count; i++)
+ {
+ staticFilterItems[i] = new FilterItem(actionDescriptor.FilterDescriptors[i]);
+ }
+
+ var allFilterItems = new List<FilterItem>(staticFilterItems);
+
+ // Execute the filter factory to determine which static filters can be cached.
+ var filters = CreateUncachedFiltersCore(filterProviders, actionContext, allFilterItems);
+
+ // Cache the filter items based on the following criteria
+ // 1. Are created statically (ex: via filter attributes, added to global filter list etc.)
+ // 2. Are re-usable
+ for (var i = 0; i < staticFilterItems.Length; i++)
+ {
+ var item = staticFilterItems[i];
+ if (!item.IsReusable)
+ {
+ item.Filter = null;
+ }
+ }
+
+ return new FilterFactoryResult(staticFilterItems, filters);
+ }
+
+ public static IFilterMetadata[] CreateUncachedFilters(
+ IFilterProvider[] filterProviders,
+ ActionContext actionContext,
+ FilterItem[] cachedFilterItems)
+ {
+ if (filterProviders == null)
+ {
+ throw new ArgumentNullException(nameof(filterProviders));
+ }
+
+ if (actionContext == null)
+ {
+ throw new ArgumentNullException(nameof(actionContext));
+ }
+
+ if (cachedFilterItems == null)
+ {
+ throw new ArgumentNullException(nameof(cachedFilterItems));
+ }
+
+ // Deep copy the cached filter items as filter providers could modify them
+ var filterItems = new List<FilterItem>(cachedFilterItems.Length);
+ for (var i = 0; i < cachedFilterItems.Length; i++)
+ {
+ var filterItem = cachedFilterItems[i];
+ filterItems.Add(
+ new FilterItem(filterItem.Descriptor)
+ {
+ Filter = filterItem.Filter,
+ IsReusable = filterItem.IsReusable
+ });
+ }
+
+ return CreateUncachedFiltersCore(filterProviders, actionContext, filterItems);
+ }
+
+ private static IFilterMetadata[] CreateUncachedFiltersCore(
+ IFilterProvider[] filterProviders,
+ ActionContext actionContext,
+ List<FilterItem> filterItems)
+ {
+ // Execute providers
+ var context = new FilterProviderContext(actionContext, filterItems);
+
+ for (var i = 0; i < filterProviders.Length; i++)
+ {
+ filterProviders[i].OnProvidersExecuting(context);
+ }
+
+ for (var i = filterProviders.Length - 1; i >= 0; i--)
+ {
+ filterProviders[i].OnProvidersExecuted(context);
+ }
+
+ // Extract filter instances from statically defined filters and filter providers
+ var count = 0;
+ for (var i = 0; i < filterItems.Count; i++)
+ {
+ if (filterItems[i].Filter != null)
+ {
+ count++;
+ }
+ }
+
+ if (count == 0)
+ {
+ return EmptyArray<IFilterMetadata>.Instance;
+ }
+ else
+ {
+ var filters = new IFilterMetadata[count];
+ var filterIndex = 0;
+ for (int i = 0; i < filterItems.Count; i++)
+ {
+ var filter = filterItems[i].Filter;
+ if (filter != null)
+ {
+ filters[filterIndex++] = filter;
+ }
+ }
+
+ return filters;
+ }
+ }
+ }
+}
@@ -0,0 +1,22 @@
+// 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 Microsoft.AspNetCore.Mvc.Filters;
+
+namespace Microsoft.AspNetCore.Mvc.Internal
+{
+ public struct FilterFactoryResult
+ {
+ public FilterFactoryResult(
+ FilterItem[] cacheableFilters,
+ IFilterMetadata[] filters)
+ {
+ CacheableFilters = cacheableFilters;
+ Filters = filters;
+ }
+
+ public FilterItem[] CacheableFilters { get; }
+
+ public IFilterMetadata[] Filters { get; }
+ }
+}
@@ -3,23 +3,28 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Abstractions;
+using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Internal;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
public class PageActionInvoker : IActionInvoker
{
- private readonly PageActionInvokerCacheEntry _cacheEntry;
private readonly ActionContext _actionContext;
+ private readonly IFilterMetadata[] _filters;
public PageActionInvoker(
PageActionInvokerCacheEntry cacheEntry,
- ActionContext actionContext)
+ ActionContext actionContext,
+ IFilterMetadata[] filters)
{
- _cacheEntry = cacheEntry;
+ CacheEntry = cacheEntry;
_actionContext = actionContext;
+ _filters = filters;
}
+ public PageActionInvokerCacheEntry CacheEntry { get; }
+
public Task InvokeAsync()
{
return TaskCache.CompletedTask;
@@ -12,12 +12,12 @@ public class PageActionInvokerCacheEntry
CompiledPageActionDescriptor actionDescriptor,
Func<PageContext, object> pageFactory,
Action<PageContext, object> releasePage,
- Func<PageContext, IFilterMetadata[]> filterProvider)
+ FilterItem[] cacheableFilters)
{
ActionDescriptor = actionDescriptor;
PageFactory = pageFactory;
ReleasePage = releasePage;
- FilterProvider = filterProvider;
+ CacheableFilters = cacheableFilters;
}
public CompiledPageActionDescriptor ActionDescriptor { get; }
@@ -29,6 +29,6 @@ public class PageActionInvokerCacheEntry
/// </summary>
public Action<PageContext, object> ReleasePage { get; }
- Func<PageContext, IFilterMetadata[]> FilterProvider { get; }
+ public FilterItem[] CacheableFilters { get; }
}
}
Oops, something went wrong.

0 comments on commit 6b0282f

Please sign in to comment.