// 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; } } } }