Munch on less memory when handling property metadata
- #5499 - switch `foreach` to `for` and use less Linq when accessing `modelMetadata.Properties` - change backing field for `ModelExplorer.Properties` from a list to an array
This commit is contained in:
parent
48546dbb28
commit
7178464ed2
|
|
@ -623,7 +623,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
||||||
//
|
//
|
||||||
if (modelMetadata.IsEnumerableType ||
|
if (modelMetadata.IsEnumerableType ||
|
||||||
!modelMetadata.IsComplexType ||
|
!modelMetadata.IsComplexType ||
|
||||||
!modelMetadata.Properties.Any())
|
modelMetadata.Properties.Count == 0)
|
||||||
{
|
{
|
||||||
Context.Results.Add(CreateResult(bindingContext, source ?? ambientSource, containerName));
|
Context.Results.Add(CreateResult(bindingContext, source ?? ambientSource, containerName));
|
||||||
return;
|
return;
|
||||||
|
|
@ -656,10 +656,10 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
||||||
newContainerName = GetName(containerName, bindingContext);
|
newContainerName = GetName(containerName, bindingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var propertyMetadata in modelMetadata.Properties)
|
for (var i = 0; i < modelMetadata.Properties.Count; i++)
|
||||||
{
|
{
|
||||||
|
var propertyMetadata = modelMetadata.Properties[i];
|
||||||
var key = new PropertyKey(propertyMetadata, source);
|
var key = new PropertyKey(propertyMetadata, source);
|
||||||
|
|
||||||
var propertyContext = ApiParameterDescriptionContext.GetContext(
|
var propertyContext = ApiParameterDescriptionContext.GetContext(
|
||||||
propertyMetadata,
|
propertyMetadata,
|
||||||
bindingInfo: null,
|
bindingInfo: null,
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
||||||
bindingContext.Model = CreateModel(bindingContext);
|
bindingContext.Model = CreateModel(bindingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var property in bindingContext.ModelMetadata.Properties)
|
for (var i = 0; i < bindingContext.ModelMetadata.Properties.Count; i++)
|
||||||
{
|
{
|
||||||
|
var property = bindingContext.ModelMetadata.Properties[i];
|
||||||
if (!CanBindProperty(bindingContext, property))
|
if (!CanBindProperty(bindingContext, property))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -228,8 +229,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
||||||
//
|
//
|
||||||
var hasBindableProperty = false;
|
var hasBindableProperty = false;
|
||||||
var isAnyPropertyEnabledForValueProviderBasedBinding = false;
|
var isAnyPropertyEnabledForValueProviderBasedBinding = false;
|
||||||
foreach (var propertyMetadata in bindingContext.ModelMetadata.Properties)
|
for (var i = 0; i < bindingContext.ModelMetadata.Properties.Count; i++)
|
||||||
{
|
{
|
||||||
|
var propertyMetadata = bindingContext.ModelMetadata.Properties[i];
|
||||||
if (!CanBindProperty(bindingContext, propertyMetadata))
|
if (!CanBindProperty(bindingContext, propertyMetadata))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
// 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;
|
using System;
|
||||||
using System.Reflection;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
||||||
{
|
{
|
||||||
|
|
@ -25,8 +25,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
||||||
HasDefaultConstructor(context.Metadata.ModelType.GetTypeInfo()))
|
HasDefaultConstructor(context.Metadata.ModelType.GetTypeInfo()))
|
||||||
{
|
{
|
||||||
var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
|
var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
|
||||||
foreach (var property in context.Metadata.Properties)
|
for (var i = 0; i < context.Metadata.Properties.Count; i++)
|
||||||
{
|
{
|
||||||
|
var property = context.Metadata.Properties[i];
|
||||||
propertyBinders.Add(property, context.CreateBinder(property));
|
propertyBinders.Add(property, context.CreateBinder(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -463,8 +463,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Internal
|
||||||
}
|
}
|
||||||
else if (modelMetadata.IsComplexType)
|
else if (modelMetadata.IsComplexType)
|
||||||
{
|
{
|
||||||
foreach (var property in modelMetadata.Properties)
|
for (var i = 0; i < modelMetadata.Properties.Count; i++)
|
||||||
{
|
{
|
||||||
|
var property = modelMetadata.Properties[i];
|
||||||
modelState.ClearValidationState(property.BinderModelName ?? property.PropertyName);
|
modelState.ClearValidationState(property.BinderModelName ?? property.PropertyName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,9 +129,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
if (string.IsNullOrEmpty(modelKey))
|
if (string.IsNullOrEmpty(modelKey))
|
||||||
{
|
{
|
||||||
var modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(TModel));
|
var modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(TModel));
|
||||||
|
for (var i = 0; i < modelMetadata.Properties.Count; i++)
|
||||||
foreach (var property in modelMetadata.Properties)
|
|
||||||
{
|
{
|
||||||
|
var property = modelMetadata.Properties[i];
|
||||||
var childKey = property.BinderModelName ?? property.PropertyName;
|
var childKey = property.BinderModelName ?? property.PropertyName;
|
||||||
var entries = modelState.FindKeysWithPrefix(childKey).ToArray();
|
var entries = modelState.FindKeysWithPrefix(childKey).ToArray();
|
||||||
foreach (var entry in entries)
|
foreach (var entry in entries)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
|
|
@ -20,7 +19,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
|
|
||||||
private object _model;
|
private object _model;
|
||||||
private Func<object, object> _modelAccessor;
|
private Func<object, object> _modelAccessor;
|
||||||
private List<ModelExplorer> _properties;
|
private ModelExplorer[] _properties;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="ModelExplorer"/>.
|
/// Creates a new <see cref="ModelExplorer"/>.
|
||||||
|
|
@ -198,24 +197,38 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
/// Includes a <see cref="ModelExplorer"/> for each property of the <see cref="ModelMetadata"/>
|
/// Includes a <see cref="ModelExplorer"/> for each property of the <see cref="ModelMetadata"/>
|
||||||
/// for <see cref="ModelType"/>.
|
/// for <see cref="ModelType"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public IEnumerable<ModelExplorer> Properties
|
public IEnumerable<ModelExplorer> Properties => PropertiesInternal;
|
||||||
|
|
||||||
|
private ModelExplorer[] PropertiesInternal
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_properties == null)
|
if (_properties == null)
|
||||||
{
|
{
|
||||||
_properties = new List<ModelExplorer>();
|
|
||||||
|
|
||||||
var metadata = GetMetadataForRuntimeType();
|
var metadata = GetMetadataForRuntimeType();
|
||||||
|
var properties = metadata.Properties;
|
||||||
|
var propertyHelpers = PropertyHelper.GetProperties(ModelType);
|
||||||
|
|
||||||
var properties = Enumerable.Join(
|
_properties = new ModelExplorer[properties.Count];
|
||||||
metadata.Properties,
|
for (var i = 0; i < properties.Count; i++)
|
||||||
PropertyHelper.GetProperties(ModelType),
|
{
|
||||||
m => m.PropertyName,
|
var propertyMetadata = properties[i];
|
||||||
ph => ph.Property.Name,
|
PropertyHelper propertyHelper = null;
|
||||||
(m, ph) => CreateExplorerForProperty(m, ph));
|
for (var j = 0; j < propertyHelpers.Length; j++)
|
||||||
|
{
|
||||||
|
if (string.Equals(
|
||||||
|
propertyMetadata.PropertyName,
|
||||||
|
propertyHelpers[j].Property.Name,
|
||||||
|
StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
propertyHelper = propertyHelpers[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_properties.AddRange(properties);
|
Debug.Assert(propertyHelper != null);
|
||||||
|
_properties[i] = CreateExplorerForProperty(propertyMetadata, propertyHelper);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return _properties;
|
return _properties;
|
||||||
|
|
@ -252,10 +265,16 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
throw new ArgumentNullException(nameof(name));
|
throw new ArgumentNullException(nameof(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Properties.FirstOrDefault(p => string.Equals(
|
for (var i = 0; i < PropertiesInternal.Length; i++)
|
||||||
p.Metadata.PropertyName,
|
{
|
||||||
name,
|
var property = PropertiesInternal[i];
|
||||||
StringComparison.Ordinal));
|
if (string.Equals(name, property.Metadata.PropertyName, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,8 @@
|
||||||
// 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;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue