/Trunk/MvcExtensions/ModelMetadata/ExtendedModelMetadataProvider.cs

http://mvcextensions.codeplex.com · C# · 231 lines · 152 code · 45 blank · 34 comment · 40 complexity · bb7444a72e166bcd0ab4eb694dab4028 MD5 · raw file

  1. #region Copyright
  2. // Copyright (c) 2009 - 2010, Kazi Manzur Rashid <kazimanzurrashid@gmail.com>.
  3. // This source is subject to the Microsoft Public License.
  4. // See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  5. // All other rights reserved.
  6. #endregion
  7. namespace MvcExtensions
  8. {
  9. using System;
  10. using System.Collections.Generic;
  11. using System.ComponentModel;
  12. using System.Linq;
  13. using System.Web.Mvc;
  14. /// <summary>
  15. /// Defines a metadata provider which supports fluent registration.
  16. /// </summary>
  17. public class ExtendedModelMetadataProvider : DataAnnotationsModelMetadataProvider
  18. {
  19. private readonly IModelMetadataRegistry registry;
  20. /// <summary>
  21. /// Initializes a new instance of the <see cref="ExtendedModelMetadataProvider"/> class.
  22. /// </summary>
  23. /// <param name="registry">The registry.</param>
  24. public ExtendedModelMetadataProvider(IModelMetadataRegistry registry)
  25. {
  26. Invariant.IsNotNull(registry, "registry");
  27. this.registry = registry;
  28. }
  29. /// <summary>
  30. /// Gets a <see cref="T:System.Web.Mvc.ModelMetadata"/> object for each property of a model.
  31. /// </summary>
  32. /// <param name="container">The container.</param>
  33. /// <param name="containerType">The type of the container.</param>
  34. /// <returns>
  35. /// A <see cref="T:System.Web.Mvc.ModelMetadata"/> object for each property of a model.
  36. /// </returns>
  37. public override IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType)
  38. {
  39. Invariant.IsNotNull(containerType, "containerType");
  40. IDictionary<string, ModelMetadataItem> metadataItems = registry.GetModelPropertiesMetadata(containerType);
  41. if ((metadataItems == null) || (metadataItems.Count == 0))
  42. {
  43. return base.GetMetadataForProperties(container, containerType);
  44. }
  45. IList<ModelMetadata> list = new List<ModelMetadata>();
  46. foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(containerType))
  47. {
  48. ModelMetadataItem metadata;
  49. metadataItems.TryGetValue(descriptor.Name, out metadata);
  50. PropertyDescriptor tempDescriptor = descriptor;
  51. ModelMetadata modelMetadata = CreatePropertyMetadata(containerType, tempDescriptor.Name, tempDescriptor.PropertyType, metadata, () => tempDescriptor.GetValue(container));
  52. list.Add(modelMetadata);
  53. }
  54. return list;
  55. }
  56. /// <summary>
  57. /// Gets metadata for the specified property.
  58. /// </summary>
  59. /// <param name="modelAccessor">The model accessor.</param>
  60. /// <param name="containerType">The type of the container.</param>
  61. /// <param name="propertyName">The property to get the metadata model for.</param>
  62. /// <returns>
  63. /// The metadata model for the specified property.
  64. /// </returns>
  65. public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName)
  66. {
  67. Invariant.IsNotNull(containerType, "containerType");
  68. Invariant.IsNotNull(propertyName, "propertyName");
  69. ModelMetadataItem metadataItem = registry.GetModelPropertyMetadata(containerType, propertyName);
  70. if (metadataItem == null)
  71. {
  72. return base.GetMetadataForProperty(modelAccessor, containerType, propertyName);
  73. }
  74. PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties(containerType)
  75. .Cast<PropertyDescriptor>()
  76. .FirstOrDefault(property => property.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase));
  77. if (propertyDescriptor == null)
  78. {
  79. throw new ArgumentException(string.Format(Culture.CurrentUI, ExceptionMessages.ThePropertyNameOfTypeCouldNotBeFound, containerType.FullName, propertyName));
  80. }
  81. return CreatePropertyMetadata(containerType, propertyName, propertyDescriptor.PropertyType, metadataItem, modelAccessor);
  82. }
  83. /// <summary>
  84. /// Gets metadata for the specified model accessor and model type.
  85. /// </summary>
  86. /// <param name="modelAccessor">The model accessor.</param>
  87. /// <param name="modelType">They type of the model.</param>
  88. /// <returns>The metadata.</returns>
  89. public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType)
  90. {
  91. ModelMetadataItem metadataItem = registry.GetModelMetadata(modelType);
  92. return metadataItem == null ? base.GetMetadataForType(modelAccessor, modelType) : CreateModelMetadata(modelType, modelAccessor, metadataItem);
  93. }
  94. private static void Copy(ModelMetadataItem metadataItem, ModelMetadata metadata)
  95. {
  96. metadata.ShowForDisplay = metadataItem.ShowForDisplay;
  97. if (metadataItem.DisplayName != null)
  98. {
  99. metadata.DisplayName = metadataItem.DisplayName();
  100. }
  101. if (metadataItem.ShortDisplayName != null)
  102. {
  103. metadata.ShortDisplayName = metadataItem.ShortDisplayName();
  104. }
  105. if (!string.IsNullOrEmpty(metadataItem.TemplateName))
  106. {
  107. metadata.TemplateHint = metadataItem.TemplateName;
  108. }
  109. if (metadataItem.Description != null)
  110. {
  111. metadata.Description = metadataItem.Description();
  112. }
  113. if (metadataItem.NullDisplayText != null)
  114. {
  115. metadata.NullDisplayText = metadataItem.NullDisplayText();
  116. }
  117. if (metadataItem.Watermark != null)
  118. {
  119. metadata.Watermark = metadataItem.Watermark();
  120. }
  121. if (metadataItem.HideSurroundingHtml.HasValue)
  122. {
  123. metadata.HideSurroundingHtml = metadataItem.HideSurroundingHtml.Value;
  124. }
  125. if (metadataItem.RequestValidationEnabled.HasValue)
  126. {
  127. metadata.RequestValidationEnabled = metadataItem.RequestValidationEnabled.Value;
  128. }
  129. if (metadataItem.IsReadOnly.HasValue)
  130. {
  131. metadata.IsReadOnly = metadataItem.IsReadOnly.Value;
  132. }
  133. if (metadataItem.IsRequired.HasValue)
  134. {
  135. metadata.IsRequired = metadataItem.IsRequired.Value;
  136. }
  137. if (metadataItem.ShowForEdit.HasValue)
  138. {
  139. metadata.ShowForEdit = metadataItem.ShowForEdit.Value;
  140. }
  141. else
  142. {
  143. metadata.ShowForEdit = !metadata.IsReadOnly;
  144. }
  145. if (metadataItem.Order.HasValue)
  146. {
  147. metadata.Order = metadataItem.Order.Value;
  148. }
  149. var formattableItem = metadataItem as IModelMetadataFormattableItem;
  150. if (formattableItem != null)
  151. {
  152. if (formattableItem.DisplayFormat != null)
  153. {
  154. metadata.DisplayFormatString = formattableItem.DisplayFormat();
  155. }
  156. if (formattableItem.ApplyFormatInEditMode && metadata.ShowForEdit && formattableItem.EditFormat != null)
  157. {
  158. metadata.EditFormatString = formattableItem.EditFormat();
  159. }
  160. }
  161. var stringMetadataItem = metadataItem as ModelMetadataItem;
  162. if (stringMetadataItem != null)
  163. {
  164. metadata.ConvertEmptyStringToNull = stringMetadataItem.ConvertEmptyStringToNull;
  165. }
  166. }
  167. private ModelMetadata CreatePropertyMetadata(Type containerType, string propertyName, Type propertyType, ModelMetadataItem propertyMetadata, Func<object> modelAccessor)
  168. {
  169. ModelMetadata modelMetadata = new ExtendedModelMetadata(this, containerType, modelAccessor, propertyType, propertyName, propertyMetadata);
  170. if (propertyMetadata != null)
  171. {
  172. Copy(propertyMetadata, modelMetadata);
  173. }
  174. return modelMetadata;
  175. }
  176. private ModelMetadata CreateModelMetadata(Type modelType, Func<object> modelAccessor, ModelMetadataItem metadataItem)
  177. {
  178. ModelMetadata modelMetadata = new ExtendedModelMetadata(this, null, modelAccessor, modelType, null, metadataItem);
  179. if (metadataItem != null)
  180. {
  181. Copy(metadataItem, modelMetadata);
  182. }
  183. return modelMetadata;
  184. }
  185. }
  186. }