Use a copy on write list for items in Resource Filters
We allocate a separate list for model-binding related objects when we create the resource filter contexts, and these lists then live the lifetime of the request. These *may* be modified by user code in filters as a supported feature, but rarely are changed in practice. This change adds a simple CopyOnWriteList implementation to reduce the amount of copying that's actually done.
This commit is contained in:
parent
581d738732
commit
d74e81186b
|
|
@ -7,6 +7,7 @@ using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Mvc.Internal;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
|
|
@ -241,11 +242,11 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
|
|
||||||
var context = new ResourceExecutingContext(ActionContext, _filters);
|
var context = new ResourceExecutingContext(ActionContext, _filters);
|
||||||
|
|
||||||
context.InputFormatters = new List<IInputFormatter>(_inputFormatters);
|
context.InputFormatters = new CopyOnWriteList<IInputFormatter>(_inputFormatters);
|
||||||
context.OutputFormatters = new List<IOutputFormatter>(_outputFormatters);
|
context.OutputFormatters = new CopyOnWriteList<IOutputFormatter>(_outputFormatters);
|
||||||
context.ModelBinders = new List<IModelBinder>(_modelBinders);
|
context.ModelBinders = new CopyOnWriteList<IModelBinder>(_modelBinders);
|
||||||
context.ValidatorProviders = new List<IModelValidatorProvider>(_modelValidatorProviders);
|
context.ValidatorProviders = new CopyOnWriteList<IModelValidatorProvider>(_modelValidatorProviders);
|
||||||
context.ValueProviderFactories = new List<IValueProviderFactory>(_valueProviderFactories);
|
context.ValueProviderFactories = new CopyOnWriteList<IValueProviderFactory>(_valueProviderFactories);
|
||||||
|
|
||||||
_resourceExecutingContext = context;
|
_resourceExecutingContext = context;
|
||||||
await InvokeResourceFilterAsync();
|
await InvokeResourceFilterAsync();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
// 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.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Internal
|
||||||
|
{
|
||||||
|
public class CopyOnWriteList<T> : IList<T>
|
||||||
|
{
|
||||||
|
private readonly IReadOnlyList<T> _source;
|
||||||
|
private List<T> _copy;
|
||||||
|
|
||||||
|
public CopyOnWriteList(IReadOnlyList<T> source)
|
||||||
|
{
|
||||||
|
_source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IReadOnlyList<T> Readable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _copy ?? _source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<T> Writable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_copy == null)
|
||||||
|
{
|
||||||
|
_copy = new List<T>(_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Readable[index];
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Writable[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Readable.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsReadOnly
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(T item)
|
||||||
|
{
|
||||||
|
Writable.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
Writable.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(T item)
|
||||||
|
{
|
||||||
|
foreach (var obj in Readable)
|
||||||
|
{
|
||||||
|
if (object.Equals(obj, item))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(T[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
foreach (var item in Readable)
|
||||||
|
{
|
||||||
|
array[arrayIndex++] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<T> GetEnumerator()
|
||||||
|
{
|
||||||
|
return Readable.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int IndexOf(T item)
|
||||||
|
{
|
||||||
|
var i = 0;
|
||||||
|
foreach (var obj in Readable)
|
||||||
|
{
|
||||||
|
if (object.Equals(obj, item))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Insert(int index, T item)
|
||||||
|
{
|
||||||
|
Writable.Insert(index, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(T item)
|
||||||
|
{
|
||||||
|
return Writable.Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAt(int index)
|
||||||
|
{
|
||||||
|
Writable.RemoveAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue