GetMetadataForProperty()
объявлено для класса ModelMetadataProvider
.
AssociatedMetadataProvider
происходит от ModelMetadataProvider
. CreateMetadata()
объявлено AssociatedMetadataProvider
. Значение DataAnnotationsMetadataProvider
, которое переопределено в указанной вами ссылке, получено из AssociatedMetadataProvider
.
Инфраструктура MVC выполняет вызовы ModelMetadataProvider
GetMetadataForProperty()
метода.
Причина, по которой переопределение CreateMetadata()
работает для вас, заключается в том, что реализация GetMetadataForProperty()
по умолчанию *1019* делает вызов CreateMetadata()
. Это выглядит так:
public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName)
{
if (containerType == null)
{
throw new ArgumentNullException("containerType");
}
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "propertyName");
}
PropertyDescriptor propertyDescriptor = this.GetTypeDescriptor(containerType).GetProperties().Find(propertyName, true);
if (propertyDescriptor == null)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MvcResources.Common_PropertyNotFound, new object[] { containerType.FullName, propertyName }));
}
return this.GetMetadataForProperty(modelAccessor, containerType, propertyDescriptor);
}
protected virtual ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, PropertyDescriptor propertyDescriptor)
{
IEnumerable<Attribute> attributes = this.FilterAttributes(containerType, propertyDescriptor, propertyDescriptor.Attributes.Cast<Attribute>());
return this.CreateMetadata(attributes, containerType, modelAccessor, propertyDescriptor.PropertyType, propertyDescriptor.Name);
}
Если вы подклассифицируете AssociatedMetadataProvider
по той ссылке, которую вы указали, то предпочитаемым пунктом расширения является метод CreateMetadata
, поскольку метод AssociatedMetadataProvider.GetMetadataForProperty()
предварительно проверяет контракт вашего метода CreateMetadata()
. Таким образом, вы знаете, что если в вашем методе CreateMetadata()
есть ошибка, вы уже знаете, что источник ошибки находится в вашем методе, а не в аргументах, которые ему были переданы.
Также, вот источник FilterAttributes()
метода, если вам интересно:
protected virtual IEnumerable<Attribute> FilterAttributes(Type containerType, PropertyDescriptor propertyDescriptor, IEnumerable<Attribute> attributes)
{
if (!typeof(ViewPage).IsAssignableFrom(containerType) && !typeof(ViewUserControl).IsAssignableFrom(containerType))
{
return attributes;
}
return attributes.Where<Attribute>(delegate (Attribute a) {
return !(a is ReadOnlyAttribute);
});
}