// 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;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
#if DOTNET5_4
using System.Reflection;
#endif
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
{
///
/// A default implementation.
///
public class DefaultModelMetadata : ModelMetadata
{
private readonly IModelMetadataProvider _provider;
private readonly ICompositeMetadataDetailsProvider _detailsProvider;
private readonly DefaultMetadataDetails _details;
private ReadOnlyDictionary _additionalValues;
private ModelMetadata _elementMetadata;
private bool? _isBindingRequired;
private bool? _isReadOnly;
private bool? _isRequired;
private ModelPropertyCollection _properties;
private ReadOnlyCollection _validatorMetadata;
///
/// Creates a new .
///
/// The .
/// The .
/// The .
public DefaultModelMetadata(
IModelMetadataProvider provider,
ICompositeMetadataDetailsProvider detailsProvider,
DefaultMetadataDetails details)
: base(details.Key)
{
if (provider == null)
{
throw new ArgumentNullException(nameof(provider));
}
if (detailsProvider == null)
{
throw new ArgumentNullException(nameof(detailsProvider));
}
if (details == null)
{
throw new ArgumentNullException(nameof(details));
}
_provider = provider;
_detailsProvider = detailsProvider;
_details = details;
}
///
/// Gets the set of attributes for the current instance.
///
public ModelAttributes Attributes
{
get
{
return _details.ModelAttributes;
}
}
///
/// Gets the for the current instance.
///
///
/// Accessing this property will populate the if necessary.
///
public BindingMetadata BindingMetadata
{
get
{
if (_details.BindingMetadata == null)
{
var context = new BindingMetadataProviderContext(Identity, _details.ModelAttributes);
_detailsProvider.GetBindingMetadata(context);
_details.BindingMetadata = context.BindingMetadata;
}
return _details.BindingMetadata;
}
}
///
/// Gets the for the current instance.
///
///
/// Accessing this property will populate the if necessary.
///
public DisplayMetadata DisplayMetadata
{
get
{
if (_details.DisplayMetadata == null)
{
var context = new DisplayMetadataProviderContext(Identity, _details.ModelAttributes);
_detailsProvider.GetDisplayMetadata(context);
_details.DisplayMetadata = context.DisplayMetadata;
}
return _details.DisplayMetadata;
}
}
///
/// Gets the for the current instance.
///
///
/// Accessing this property will populate the if necessary.
///
public ValidationMetadata ValidationMetadata
{
get
{
if (_details.ValidationMetadata == null)
{
var context = new ValidationMetadataProviderContext(Identity, _details.ModelAttributes);
_detailsProvider.GetValidationMetadata(context);
_details.ValidationMetadata = context.ValidationMetadata;
}
return _details.ValidationMetadata;
}
}
///
public override IReadOnlyDictionary AdditionalValues
{
get
{
if (_additionalValues == null)
{
_additionalValues = new ReadOnlyDictionary(DisplayMetadata.AdditionalValues);
}
return _additionalValues;
}
}
///
public override BindingSource BindingSource
{
get
{
return BindingMetadata.BindingSource;
}
}
///
public override string BinderModelName
{
get
{
return BindingMetadata.BinderModelName;
}
}
///
public override Type BinderType
{
get
{
return BindingMetadata.BinderType;
}
}
///
public override bool ConvertEmptyStringToNull
{
get
{
return DisplayMetadata.ConvertEmptyStringToNull;
}
}
///
public override string DataTypeName
{
get
{
return DisplayMetadata.DataTypeName;
}
}
///
public override string Description
{
get
{
if (DisplayMetadata.Description == null)
{
return null;
}
return DisplayMetadata.Description();
}
}
///
public override string DisplayFormatString
{
get
{
return DisplayMetadata.DisplayFormatString;
}
}
///
public override string DisplayName
{
get
{
if (DisplayMetadata.DisplayName == null)
{
return null;
}
return DisplayMetadata.DisplayName();
}
}
///
public override string EditFormatString
{
get
{
return DisplayMetadata.EditFormatString;
}
}
///
public override ModelMetadata ElementMetadata
{
get
{
if (_elementMetadata == null && ElementType != null)
{
_elementMetadata = _provider.GetMetadataForType(ElementType);
}
return _elementMetadata;
}
}
///
public override IEnumerable> EnumGroupedDisplayNamesAndValues
{
get
{
return DisplayMetadata.EnumGroupedDisplayNamesAndValues;
}
}
///
public override IReadOnlyDictionary EnumNamesAndValues
{
get
{
return DisplayMetadata.EnumNamesAndValues;
}
}
///
public override bool HasNonDefaultEditFormat
{
get
{
return DisplayMetadata.HasNonDefaultEditFormat;
}
}
///
public override bool HideSurroundingHtml
{
get
{
return DisplayMetadata.HideSurroundingHtml;
}
}
///
public override bool HtmlEncode
{
get
{
return DisplayMetadata.HtmlEncode;
}
}
///
public override bool IsBindingAllowed
{
get
{
if (MetadataKind == ModelMetadataKind.Property)
{
return BindingMetadata.IsBindingAllowed;
}
else
{
return true;
}
}
}
///
public override bool IsBindingRequired
{
get
{
if (!_isBindingRequired.HasValue)
{
if (MetadataKind == ModelMetadataKind.Type)
{
_isBindingRequired = false;
}
else
{
_isBindingRequired = BindingMetadata.IsBindingRequired;
}
}
return _isBindingRequired.Value;
}
}
///
public override bool IsEnum
{
get
{
return DisplayMetadata.IsEnum;
}
}
///
public override bool IsFlagsEnum
{
get
{
return DisplayMetadata.IsFlagsEnum;
}
}
///
public override bool IsReadOnly
{
get
{
if (!_isReadOnly.HasValue)
{
if (MetadataKind == ModelMetadataKind.Type)
{
_isReadOnly = false;
}
else if (BindingMetadata.IsReadOnly.HasValue)
{
_isReadOnly = BindingMetadata.IsReadOnly;
}
else
{
_isReadOnly = _details.PropertySetter == null;
}
}
return _isReadOnly.Value;
}
}
///
public override bool IsRequired
{
get
{
if (!_isRequired.HasValue)
{
if (ValidationMetadata.IsRequired.HasValue)
{
_isRequired = ValidationMetadata.IsRequired;
}
else
{
// Default to IsRequired = true for non-Nullable value types.
_isRequired = !IsReferenceOrNullableType;
}
}
return _isRequired.Value;
}
}
///
public override IModelBindingMessageProvider ModelBindingMessageProvider
{
get
{
return BindingMetadata.ModelBindingMessageProvider;
}
}
///
public override string NullDisplayText
{
get
{
return DisplayMetadata.NullDisplayText;
}
}
///
public override int Order
{
get
{
return DisplayMetadata.Order;
}
}
///
public override ModelPropertyCollection Properties
{
get
{
if (_properties == null)
{
var properties = _provider.GetMetadataForProperties(ModelType);
properties = properties.OrderBy(p => p.Order);
_properties = new ModelPropertyCollection(properties);
}
return _properties;
}
}
///
public override IPropertyBindingPredicateProvider PropertyBindingPredicateProvider
{
get
{
return BindingMetadata.PropertyBindingPredicateProvider;
}
}
///
public override bool ShowForDisplay
{
get
{
return DisplayMetadata.ShowForDisplay;
}
}
///
public override bool ShowForEdit
{
get
{
return DisplayMetadata.ShowForEdit;
}
}
///
public override string SimpleDisplayProperty
{
get
{
return DisplayMetadata.SimpleDisplayProperty;
}
}
///
public override string TemplateHint
{
get
{
return DisplayMetadata.TemplateHint;
}
}
///
public override IReadOnlyList ValidatorMetadata
{
get
{
if (_validatorMetadata == null)
{
_validatorMetadata = new ReadOnlyCollection(ValidationMetadata.ValidatorMetadata);
}
return _validatorMetadata;
}
}
///
public override Func PropertyGetter
{
get
{
return _details.PropertyGetter;
}
}
///
public override Action PropertySetter
{
get
{
return _details.PropertySetter;
}
}
}
}