parent
b3a65b485f
commit
0788edbd4b
|
|
@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
{
|
||||
private readonly TypeCache _typeCache = new TypeCache();
|
||||
private readonly Func<ModelMetadataIdentity, ModelMetadataCacheEntry> _cacheEntryFactory;
|
||||
private readonly ModelMetadataCacheEntry _metadataCacheEntryForObjectType;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="DefaultModelMetadataProvider"/>.
|
||||
|
|
@ -26,6 +27,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
DetailsProvider = detailsProvider;
|
||||
|
||||
_cacheEntryFactory = CreateCacheEntry;
|
||||
|
||||
_metadataCacheEntryForObjectType = GetMetadataCacheEntryForObjectType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -41,14 +44,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
throw new ArgumentNullException(nameof(modelType));
|
||||
}
|
||||
|
||||
var key = ModelMetadataIdentity.ForType(modelType);
|
||||
|
||||
var cacheEntry = _typeCache.GetOrAdd(key, _cacheEntryFactory);
|
||||
var cacheEntry = GetCacheEntry(modelType);
|
||||
|
||||
// We're relying on a safe race-condition for Properties - take care only
|
||||
// to set the value onces the properties are fully-initialized.
|
||||
if (cacheEntry.Details.Properties == null)
|
||||
{
|
||||
var key = ModelMetadataIdentity.ForType(modelType);
|
||||
var propertyDetails = CreatePropertyDetails(key);
|
||||
|
||||
var properties = new ModelMetadata[propertyDetails.Length];
|
||||
|
|
@ -71,12 +73,30 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
throw new ArgumentNullException(nameof(modelType));
|
||||
}
|
||||
|
||||
var key = ModelMetadataIdentity.ForType(modelType);
|
||||
var cacheEntry = GetCacheEntry(modelType);
|
||||
|
||||
var cacheEntry = _typeCache.GetOrAdd(key, _cacheEntryFactory);
|
||||
return cacheEntry.Metadata;
|
||||
}
|
||||
|
||||
private ModelMetadataCacheEntry GetCacheEntry(Type modelType)
|
||||
{
|
||||
ModelMetadataCacheEntry cacheEntry;
|
||||
|
||||
// Perf: We cached model metadata cache entry for "object" type to save ConcurrentDictionary lookups.
|
||||
if (modelType == typeof(object))
|
||||
{
|
||||
cacheEntry = _metadataCacheEntryForObjectType;
|
||||
}
|
||||
else
|
||||
{
|
||||
var key = ModelMetadataIdentity.ForType(modelType);
|
||||
|
||||
cacheEntry = _typeCache.GetOrAdd(key, _cacheEntryFactory);
|
||||
}
|
||||
|
||||
return cacheEntry;
|
||||
}
|
||||
|
||||
private ModelMetadataCacheEntry CreateCacheEntry(ModelMetadataIdentity key)
|
||||
{
|
||||
var details = CreateTypeDetails(key);
|
||||
|
|
@ -84,6 +104,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
return new ModelMetadataCacheEntry(metadata, details);
|
||||
}
|
||||
|
||||
private ModelMetadataCacheEntry GetMetadataCacheEntryForObjectType()
|
||||
{
|
||||
var key = ModelMetadataIdentity.ForType(typeof(object));
|
||||
var entry = CreateCacheEntry(key);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ModelMetadata"/> from a <see cref="DefaultMetadataDetails"/>.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
|
||||
private ViewDataDictionary GetViewDataDictionary(ControllerContext context)
|
||||
{
|
||||
var serviceProvider = context.HttpContext.RequestServices;
|
||||
return new ViewDataDictionary(
|
||||
_modelMetadataProvider,
|
||||
context.ModelState);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,20 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
|
|||
Assert.Same(metadata1.ValidationMetadata, metadata2.ValidationMetadata);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetMetadataForObjectType_Cached()
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
// Act
|
||||
var metadata1 = provider.GetMetadataForType(typeof(object));
|
||||
var metadata2 = provider.GetMetadataForType(typeof(object));
|
||||
|
||||
// Assert
|
||||
Assert.Same(metadata1, metadata2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetMetadataForProperties_IncludesAllProperties()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1074,9 +1074,14 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations.Internal
|
|||
protected override DefaultMetadataDetails CreateTypeDetails(ModelMetadataIdentity key)
|
||||
{
|
||||
var entry = base.CreateTypeDetails(key);
|
||||
return new DefaultMetadataDetails(
|
||||
key,
|
||||
new ModelAttributes(_attributes.Concat(entry.ModelAttributes.TypeAttributes).ToArray()));
|
||||
if (_attributes?.Length > 0)
|
||||
{
|
||||
return new DefaultMetadataDetails(
|
||||
key,
|
||||
new ModelAttributes(_attributes.Concat(entry.ModelAttributes.TypeAttributes).ToArray()));
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
protected override DefaultMetadataDetails[] CreatePropertyDetails(ModelMetadataIdentity key)
|
||||
|
|
|
|||
Loading…
Reference in New Issue