/// <summary> /// Creates a new <see cref="DefaultModelMetadata"/>. /// </summary> /// <param name="provider">The <see cref="IModelMetadataProvider"/>.</param> /// <param name="detailsProvider">The <see cref="ICompositeMetadataDetailsProvider"/>.</param> /// <param name="cache">The <see cref="DefaultMetadataDetailsCache"/>.</param> public DefaultModelMetadata( [NotNull] IModelMetadataProvider provider, [NotNull] ICompositeMetadataDetailsProvider detailsProvider, [NotNull] DefaultMetadataDetailsCache cache) : base(cache.Key) { _provider = provider; _detailsProvider = detailsProvider; _cache = cache; }
public void DefaultValues() { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new DefaultCompositeMetadataDetailsProvider( Enumerable.Empty <IMetadataDetailsProvider>()); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); // Act var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); // Assert Assert.NotNull(metadata.AdditionalValues); Assert.Empty(metadata.AdditionalValues); Assert.Equal(typeof(string), metadata.ModelType); Assert.True(metadata.ConvertEmptyStringToNull); Assert.False(metadata.HasNonDefaultEditFormat); Assert.False(metadata.HideSurroundingHtml); Assert.True(metadata.HtmlEncode); Assert.False(metadata.IsComplexType); Assert.False(metadata.IsCollectionType); Assert.False(metadata.IsEnum); Assert.False(metadata.IsFlagsEnum); Assert.False(metadata.IsNullableValueType); Assert.False(metadata.IsReadOnly); Assert.False(metadata.IsRequired); Assert.True(metadata.ShowForDisplay); Assert.True(metadata.ShowForEdit); Assert.Null(metadata.DataTypeName); Assert.Null(metadata.Description); Assert.Null(metadata.DisplayFormatString); Assert.Null(metadata.DisplayName); Assert.Null(metadata.EditFormatString); Assert.Null(metadata.EnumDisplayNamesAndValues); Assert.Null(metadata.EnumNamesAndValues); Assert.Null(metadata.NullDisplayText); Assert.Null(metadata.TemplateHint); Assert.Null(metadata.SimpleDisplayProperty); Assert.Equal(10000, ModelMetadata.DefaultOrder); Assert.Equal(ModelMetadata.DefaultOrder, metadata.Order); Assert.Null(metadata.BinderModelName); Assert.Null(metadata.BinderType); Assert.Null(metadata.BindingSource); Assert.Null(metadata.PropertyBindingPredicateProvider); }
public void DefaultValues() { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new DefaultCompositeMetadataDetailsProvider( Enumerable.Empty<IMetadataDetailsProvider>()); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); // Act var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); // Assert Assert.NotNull(metadata.AdditionalValues); Assert.Empty(metadata.AdditionalValues); Assert.Equal(typeof(string), metadata.ModelType); Assert.True(metadata.ConvertEmptyStringToNull); Assert.False(metadata.HasNonDefaultEditFormat); Assert.False(metadata.HideSurroundingHtml); Assert.True(metadata.HtmlEncode); Assert.False(metadata.IsComplexType); Assert.False(metadata.IsCollectionType); Assert.False(metadata.IsEnum); Assert.False(metadata.IsFlagsEnum); Assert.False(metadata.IsNullableValueType); Assert.False(metadata.IsReadOnly); Assert.False(metadata.IsRequired); Assert.True(metadata.ShowForDisplay); Assert.True(metadata.ShowForEdit); Assert.Null(metadata.DataTypeName); Assert.Null(metadata.Description); Assert.Null(metadata.DisplayFormatString); Assert.Null(metadata.DisplayName); Assert.Null(metadata.EditFormatString); Assert.Null(metadata.EnumDisplayNamesAndValues); Assert.Null(metadata.EnumNamesAndValues); Assert.Null(metadata.NullDisplayText); Assert.Null(metadata.TemplateHint); Assert.Null(metadata.SimpleDisplayProperty); Assert.Equal(10000, ModelMetadata.DefaultOrder); Assert.Equal(ModelMetadata.DefaultOrder, metadata.Order); Assert.Null(metadata.BinderModelName); Assert.Null(metadata.BinderType); Assert.Null(metadata.BindingSource); Assert.Null(metadata.PropertyBindingPredicateProvider); }
public void IsRequired_ReturnsTrue_ForNonNullableTypes(Type modelType) { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var key = ModelMetadataIdentity.ForType(modelType); var cache = new DefaultMetadataDetailsCache(key, new object[0]); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); // Act var isRequired = metadata.IsRequired; // Assert Assert.True(isRequired); }
public void CreateMetadataForProperty() { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var key = ModelMetadataIdentity.ForProperty(typeof(string), "Message", typeof(Exception)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); // Act var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); // Assert Assert.Equal(typeof(string), metadata.ModelType); Assert.Equal("Message", metadata.PropertyName); Assert.Equal(typeof(Exception), metadata.ContainerType); }
public void CreateMetadataForType() { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new DefaultCompositeMetadataDetailsProvider( Enumerable.Empty<IMetadataDetailsProvider>()); var key = ModelMetadataIdentity.ForType(typeof(Exception)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); // Act var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); // Assert Assert.Equal(typeof(Exception), metadata.ModelType); Assert.Null(metadata.PropertyName); Assert.Null(metadata.ContainerType); }
public void CreateMetadataForType() { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new DefaultCompositeMetadataDetailsProvider( Enumerable.Empty <IMetadataDetailsProvider>()); var key = ModelMetadataIdentity.ForType(typeof(Exception)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); // Act var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); // Assert Assert.Equal(typeof(Exception), metadata.ModelType); Assert.Null(metadata.PropertyName); Assert.Null(metadata.ContainerType); }
public void PropertiesEnumerationEvaluatedOnce() { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); // Act var firstPropertiesEvaluation = metadata.Properties.ToList(); var secondPropertiesEvaluation = metadata.Properties.ToList(); // Assert // Identical ModelMetadata objects every time we run through the Properties collection. Assert.Equal(firstPropertiesEvaluation, secondPropertiesEvaluation); }
public void PropertiesSetOnce() { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); // Act var firstPropertiesEvaluation = metadata.Properties; var secondPropertiesEvaluation = metadata.Properties; // Assert // Same IEnumerable<ModelMetadata> object. Assert.Same(firstPropertiesEvaluation, secondPropertiesEvaluation); }
public void PropertiesProperty_CallsProvider() { // Arrange var provider = new Mock <IModelMetadataProvider>(MockBehavior.Strict); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var expectedProperties = new DefaultModelMetadata[] { new DefaultModelMetadata( provider.Object, detailsProvider, new DefaultMetadataDetailsCache( ModelMetadataIdentity.ForProperty(typeof(int), "Prop1", typeof(string)), attributes: null)), new DefaultModelMetadata( provider.Object, detailsProvider, new DefaultMetadataDetailsCache( ModelMetadataIdentity.ForProperty(typeof(int), "Prop2", typeof(string)), attributes: null)), }; provider .Setup(p => p.GetMetadataForProperties(typeof(string))) .Returns(expectedProperties); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); // Act var properties = metadata.Properties; // Assert Assert.Equal(expectedProperties.Length, properties.Count); for (var i = 0; i < expectedProperties.Length; i++) { Assert.Same(expectedProperties[i], properties[i]); } }
public void PropertiesProperty_OrdersPropertyNamesUsingOrder_ThenAsProvided( IEnumerable <KeyValuePair <string, int> > originalNamesAndOrders, IEnumerable <string> expectedNames) { // Arrange var provider = new Mock <IModelMetadataProvider>(MockBehavior.Strict); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var expectedProperties = new List <DefaultModelMetadata>(); foreach (var kvp in originalNamesAndOrders) { var propertyCache = new DefaultMetadataDetailsCache( ModelMetadataIdentity.ForProperty(typeof(int), kvp.Key, typeof(string)), attributes: null); propertyCache.DisplayMetadata = new DisplayMetadata(); propertyCache.DisplayMetadata.Order = kvp.Value; expectedProperties.Add(new DefaultModelMetadata( provider.Object, detailsProvider, propertyCache)); } provider .Setup(p => p.GetMetadataForProperties(typeof(string))) .Returns(expectedProperties); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); // Act var properties = metadata.Properties; // Assert Assert.Equal(expectedNames.Count(), properties.Count); Assert.Equal(expectedNames.ToArray(), properties.Select(p => p.PropertyName).ToArray()); }
public void CreateMetadataForParameter() { // Arrange var provider = new EmptyModelMetadataProvider(); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var methodInfo = GetType().GetMethod( "ActionMethod", BindingFlags.Instance | BindingFlags.NonPublic); var parameterInfo = methodInfo.GetParameters().Where(p => p.Name == "input").Single(); var key = ModelMetadataIdentity.ForParameter(parameterInfo); var cache = new DefaultMetadataDetailsCache(key, new object[0]); // Act var metadata = new DefaultModelMetadata(provider, detailsProvider, cache); Assert.Equal(typeof(string), metadata.ModelType); Assert.Equal("input", metadata.PropertyName); Assert.Null(metadata.ContainerType); }
/// <summary> /// Creates a new <see cref="ModelMetadata"/> from a <see cref="DefaultMetadataDetailsCache"/>. /// </summary> /// <param name="entry">The <see cref="DefaultMetadataDetailsCache"/> entry with cached data.</param> /// <returns>A new <see cref="ModelMetadata"/> instance.</returns> /// <remarks> /// <see cref="DefaultModelMetadataProvider"/> will always create instances of /// <see cref="DefaultModelMetadata"/> .Override this method to create a <see cref="ModelMetadata"/> /// of a different concrete type. /// </remarks> protected virtual ModelMetadata CreateModelMetadata(DefaultMetadataDetailsCache entry) { return(new DefaultModelMetadata(this, DetailsProvider, entry)); }
public void PropertiesProperty_OrdersPropertyNamesUsingOrder_ThenAsProvided( IEnumerable<KeyValuePair<string, int>> originalNamesAndOrders, IEnumerable<string> expectedNames) { // Arrange var provider = new Mock<IModelMetadataProvider>(MockBehavior.Strict); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var expectedProperties = new List<DefaultModelMetadata>(); foreach (var kvp in originalNamesAndOrders) { var propertyCache = new DefaultMetadataDetailsCache( ModelMetadataIdentity.ForProperty(typeof(int), kvp.Key, typeof(string)), attributes: null); propertyCache.DisplayMetadata = new DisplayMetadata(); propertyCache.DisplayMetadata.Order = kvp.Value; expectedProperties.Add(new DefaultModelMetadata( provider.Object, detailsProvider, propertyCache)); } provider .Setup(p => p.GetMetadataForProperties(typeof(string))) .Returns(expectedProperties); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); // Act var properties = metadata.Properties; // Assert Assert.Equal(expectedNames.Count(), properties.Count); Assert.Equal(expectedNames.ToArray(), properties.Select(p => p.PropertyName).ToArray()); }
public void PropertiesProperty_CallsProvider() { // Arrange var provider = new Mock<IModelMetadataProvider>(MockBehavior.Strict); var detailsProvider = new EmptyCompositeMetadataDetailsProvider(); var expectedProperties = new DefaultModelMetadata[] { new DefaultModelMetadata( provider.Object, detailsProvider, new DefaultMetadataDetailsCache( ModelMetadataIdentity.ForProperty(typeof(int), "Prop1", typeof(string)), attributes: null)), new DefaultModelMetadata( provider.Object, detailsProvider, new DefaultMetadataDetailsCache( ModelMetadataIdentity.ForProperty(typeof(int), "Prop2", typeof(string)), attributes: null)), }; provider .Setup(p => p.GetMetadataForProperties(typeof(string))) .Returns(expectedProperties); var key = ModelMetadataIdentity.ForType(typeof(string)); var cache = new DefaultMetadataDetailsCache(key, new object[0]); var metadata = new DefaultModelMetadata(provider.Object, detailsProvider, cache); // Act var properties = metadata.Properties; // Assert Assert.Equal(expectedProperties.Length, properties.Count); for (var i = 0; i < expectedProperties.Length; i++) { Assert.Same(expectedProperties[i], properties[i]); } }
/// <summary> /// Creates the <see cref="DefaultMetadataDetailsCache"/> entries for the properties of a model /// <see cref="Type"/>. /// </summary> /// <param name="key"> /// The <see cref="ModelMetadataIdentity"/> identifying the model <see cref="Type"/>. /// </param> /// <returns>A cache object for each property of the model <see cref="Type"/>.</returns> /// <remarks> /// The results of this method will be cached and used to satisfy calls to /// <see cref="GetMetadataForProperties(Type)"/>. Override this method to provide a different /// set of property data. /// </remarks> protected virtual DefaultMetadataDetailsCache[] CreatePropertyCacheEntries([NotNull] ModelMetadataIdentity key) { var propertyHelpers = PropertyHelper.GetProperties(key.ModelType); var propertyEntries = new List <DefaultMetadataDetailsCache>(propertyHelpers.Length); for (var i = 0; i < propertyHelpers.Length; i++) { var propertyHelper = propertyHelpers[i]; if (propertyHelper.Property.DeclaringType != key.ModelType) { // If this property was declared on a base type then look for the definition closest to the // the model type to see if we should include it. var ignoreProperty = false; // Walk up the hierarchy until we find the type that actally declares this // PropertyInfo. var currentType = key.ModelType.GetTypeInfo(); while (currentType != propertyHelper.Property.DeclaringType.GetTypeInfo()) { // We've found a 'more proximal' public definition var declaredProperty = currentType.GetDeclaredProperty(propertyHelper.Name); if (declaredProperty != null) { ignoreProperty = true; break; } currentType = currentType.BaseType.GetTypeInfo(); } if (ignoreProperty) { // There's a better definition, ignore this. continue; } } var propertyKey = ModelMetadataIdentity.ForProperty( propertyHelper.Property.PropertyType, propertyHelper.Name, key.ModelType); var attributes = new List <object>(ModelAttributes.GetAttributesForProperty( key.ModelType, propertyHelper.Property)); var propertyEntry = new DefaultMetadataDetailsCache(propertyKey, attributes); if (propertyHelper.Property.CanRead && propertyHelper.Property.GetMethod?.IsPrivate == true) { propertyEntry.PropertyAccessor = PropertyHelper.MakeFastPropertyGetter(propertyHelper.Property); } if (propertyHelper.Property.CanWrite && propertyHelper.Property.SetMethod?.IsPrivate == true) { propertyEntry.PropertySetter = PropertyHelper.MakeFastPropertySetter(propertyHelper.Property); } propertyEntries.Add(propertyEntry); } return(propertyEntries.ToArray()); }