/// <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;
 }
Exemple #2
0
 /// <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);
        }
        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 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);
        }
Exemple #16
0
 /// <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 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_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]);
            }
        }
Exemple #21
0
        /// <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());
        }
        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);
        }