2011-02-09 31 views
6

Tôi là statring để khám phá các điểm mở rộng của khung công tác, bắt đầu với MetadataProviders. Tôi hiện đang triển khai populating ModelMetadata.IsRequired property using RequiredAttribute thành công, nhưng tôi không thể tìm thấy sự khác biệt giữa ghi đè CreateMetadata() hoặc GetMetadataForProperty(), vì cả hai tùy chọn đều có vẻ hoạt động.ASP.NET MVC2 ModelMetadataProviders: Sự khác biệt giữa việc ghi đè CreateMetadata() và GetMetadataForProperty() là gì?

Nói chung, các ví dụ tôi đã thấy ghi đè CreateMetadata().

  • Ưu điểm và nhược điểm của việc sử dụng một trong hai tùy chọn là gì?
  • Có bất kỳ tình huống nào trong đó có một trong số các tùy chọn này không?

Ngoài ra: có tài nguyên nào tốt (blog, sách) để tìm hiểu từ điểm mở rộng này không?

Trả lời

8

GetMetadataForProperty() được khai báo trên lớp ModelMetadataProvider.

AssociatedMetadataProvider có nguồn gốc từ ModelMetadataProvider. CreateMetadata() được khai báo trên AssociatedMetadataProvider. Các DataAnnotationsMetadataProvider được ghi đè trong liên kết bạn cung cấp có nguồn gốc từ AssociatedMetadataProvider.

Khuôn khổ MVC thực hiện cuộc gọi tới phương thức 's GetMetadataForProperty().

Lý do trọng CreateMetadata() đang làm việc cho bạn là vì thực hiện mặc định của AssociatedModelMetadataProvider của GetMetadataForProperty() làm cho một cuộc gọi đến CreateMetadata(). Nó trông giống như thế này:

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

Nếu bạn đang subclassing AssociatedMetadataProvider như bạn đang ở trong liên kết mà bạn cung cấp, sau đó điểm mở rộng ưa thích của bạn là phương pháp CreateMetadata, vì AssociatedMetadataProvider.GetMetadataForProperty() phương pháp trước -giảm giá hợp đồng của phương thức CreateMetadata() của bạn. Bằng cách đó, bạn biết rằng nếu có lỗi trong phương thức CreateMetadata() của bạn, bạn đã biết rằng nguồn của lỗi nằm trong phương thức của bạn chứ không phải trong các đối số đã được truyền cho nó.

Ngoài ra, đây là nguồn gốc của phương pháp FilterAttributes(), trong trường hợp bạn đang tự hỏi:

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); 
    }); 
} 
+0

Nice! Cảm ơn câu trả lời hoàn chỉnh. – CGK

+0

Xin lỗi, tôi muốn trao tiền thưởng cho bạn, nhưng quên thực sự làm điều đó. Tôi sẽ thêm một antoher và chấp nhận nó vào ngày mai. Hội chợ là công bằng. – CGK

+0

Cảm ơn - hãy đánh giá cao điều đó. – smartcaveman

Các vấn đề liên quan