ASP.NET MVC5学习笔记之Action参数模型绑定之模型元数据和元数据提供

一. 元数据描述类型ModelMetadata 

模型元数据是对Model的描述信息,在ASP.NET MVC框架中有非常重要的作用,在模型绑定,模型验证,模型呈现等许多地方都有它的身影。描述Model元数据的基本类型是ModelMetadata,日常开发中我们建立的ViewModel,在上面的声明的许多属性最终都会反应的该类型上,它的具体定义如下:

  1 public class ModelMetadata
  2     {
  3         // 摘要: 
  4         //     默认顺序值 10000。
  5         public const int DefaultOrder = 10000;
  6 
  7         // 摘要: 
  8         //     初始化 System.Web.Mvc.ModelMetadata 类的新实例。
  9         //
 10         // 参数: 
 11         //   provider:
 12         //     提供程序。
 13         //
 14         //   containerType:
 15         //     容器的类型。
 16         //
 17         //   modelAccessor:
 18         //     模型访问器。
 19         //
 20         //   modelType:
 21         //     模型的类型。
 22         //
 23         //   propertyName:
 24         //     模型的名称。
 25         public ModelMetadata(ModelMetadataProvider provider, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName);
 26 
 27         // 摘要: 
 28         //     获取包含有关模型的其他元数据的字典。
 29         //
 30         // 返回结果: 
 31         //     包含有关模型的其他元数据的字典。
 32         public virtual Dictionary<string, object> AdditionalValues { get; }
 33         //
 34         // 摘要: 
 35         //     获取或设置模型的容器的类型。
 36         //
 37         // 返回结果: 
 38         //     模型的容器的类型。
 39         public Type ContainerType { get; }
 40         //
 41         // 摘要: 
 42         //     获取或设置一个值,该值指示在窗体中回发的空字符串是否应转换为 null。
 43         //
 44         // 返回结果: 
 45         //     如果在窗体中回发的空字符串应转换为 null,则为 true;否则为 false。默认值为 true。
 46         public virtual bool ConvertEmptyStringToNull { get; set; }
 47         //
 48         // 摘要: 
 49         //     获取或设置有关数据类型的元信息。
 50         //
 51         // 返回结果: 
 52         //     有关数据类型的元信息。
 53         public virtual string DataTypeName { get; set; }
 54         //
 55         // 摘要: 
 56         //     获取或设置模型的说明。
 57         //
 58         // 返回结果: 
 59         //     模型的说明。默认值为 null。
 60         public virtual string Description { get; set; }
 61         //
 62         // 摘要: 
 63         //     获取或设置模型的显示格式字符串。
 64         //
 65         // 返回结果: 
 66         //     模型的显示格式字符串。
 67         public virtual string DisplayFormatString { get; set; }
 68         //
 69         // 摘要: 
 70         //     获取或设置模型的显示名称。
 71         //
 72         // 返回结果: 
 73         //     模型的显示名称。
 74         public virtual string DisplayName { get; set; }
 75         //
 76         // 摘要: 
 77         //     获取或设置模型的编辑格式字符串。
 78         //
 79         // 返回结果: 
 80         //     模型的编辑格式字符串。
 81         public virtual string EditFormatString { get; set; }
 82         //
 83         // 摘要: 
 84         //     获取或设置一个值,该值指示是否应该使用关联的 HTML 元素呈现模型对象。
 85         //
 86         // 返回结果: 
 87         //     如果包含模型对象的关联 HTML 元素应包含在该对象中,则为 true;否则为 false。
 88         public virtual bool HideSurroundingHtml { get; set; }
 89         //
 90         // 摘要: 
 91         //     获取或设置一个值,该值指示模型是否为复杂类型。
 92         //
 93         // 返回结果: 
 94         //     一个值,指示 MVC 框架是否将模型视为复杂类型。
 95         public virtual bool IsComplexType { get; }
 96         //
 97         // 摘要: 
 98         //     获取一个值,该值指示类型是否可为 null。
 99         //
100         // 返回结果: 
101         //     如果该类型可为 null,则为 true;否则为 false。
102         public bool IsNullableValueType { get; }
103         //
104         // 摘要: 
105         //     获取或设置一个值,该值指示模型是否为只读。
106         //
107         // 返回结果: 
108         //     如果该模型为只读,则为 true;否则为 false。
109         public virtual bool IsReadOnly { get; set; }
110         //
111         // 摘要: 
112         //     获取或设置一个值,该值指示模型是否为必需的。
113         //
114         // 返回结果: 
115         //     如果该模型是必需的,则为 true;否则为 false。
116         public virtual bool IsRequired { get; set; }
117         //
118         // 摘要: 
119         //     获取模型的值。
120         //
121         // 返回结果: 
122         //     模型的值。有关 System.Web.Mvc.ModelMetadata 的更多信息,请参见 Brad Wilson 的博客上的文章 ASP.NET
123         //     MVC 2 Templates, Part 2: ModelMetadata
124         public object Model { get; set; }
125         //
126         // 摘要: 
127         //     获取模型的类型。
128         //
129         // 返回结果: 
130         //     模型的类型。
131         public Type ModelType { get; }
132         //
133         // 摘要: 
134         //     获取或设置要为 null 值显示的字符串。
135         //
136         // 返回结果: 
137         //     要为 null 值显示的字符串。
138         public virtual string NullDisplayText { get; set; }
139         //
140         // 摘要: 
141         //     获取或设置一个值,该值表示当前元数据的顺序。
142         //
143         // 返回结果: 
144         //     当前元数据的顺序值。
145         public virtual int Order { get; set; }
146         //
147         // 摘要: 
148         //     获取模型元数据对象的集合,这些对象描述模型的属性。
149         //
150         // 返回结果: 
151         //     用于描述模型属性的模型元数据对象的集合。
152         public virtual IEnumerable<ModelMetadata> Properties { get; }
153         //
154         // 摘要: 
155         //     获取属性名称。
156         //
157         // 返回结果: 
158         //     属性名称。
159         public string PropertyName { get; }
160         //
161         // 摘要: 
162         //     获取或设置提供程序。
163         //
164         // 返回结果: 
165         //     提供程序。
166         protected ModelMetadataProvider Provider { get; set; }
167         //
168         // 摘要: 
169         //     获取或设置一个值,该值指示是否启用请求验证。
170         //
171         // 返回结果: 
172         //     如果启用了请求验证,则为 true;否则为 false。
173         public virtual bool RequestValidationEnabled { get; set; }
174         //
175         // 摘要: 
176         //     获取或设置短显示名称。
177         //
178         // 返回结果: 
179         //     短显示名称。
180         public virtual string ShortDisplayName { get; set; }
181         //
182         // 摘要: 
183         //     获取或设置一个值,该值指示属性是否应显示在只读视图(如列表和详细信息视图)中。
184         //
185         // 返回结果: 
186         //     如果应在只读视图中显示模型,则为 true;否则为 false。
187         public virtual bool ShowForDisplay { get; set; }
188         //
189         // 摘要: 
190         //     获取或设置一个值,该值指示是否应在可编辑视图中显示模型。
191         //
192         // 返回结果: 
193         //     如果应在可编辑视图中显示模型,则为 true;否则为 false。
194         public virtual bool ShowForEdit { get; set; }
195         //
196         // 摘要: 
197         //     获取或设置模型的简单显示字符串。
198         //
199         // 返回结果: 
200         //     模型的简单显示字符串。
201         public virtual string SimpleDisplayText { get; set; }
202         //
203         // 摘要: 
204         //     获取或设置一个提示,该提示建议要为此模型使用哪个模板。
205         //
206         // 返回结果: 
207         //     一个提示,建议要为此模型使用哪个模板。
208         public virtual string TemplateHint { get; set; }
209         //
210         // 摘要: 
211         //     获取或设置可用作水印的值。
212         //
213         // 返回结果: 
214         //     水印。
215         public virtual string Watermark { get; set; }
216 
217         // 摘要: 
218         //     从模型的 System.Linq.Expressions.Expression 参数返回元数据。
219         //
220         // 参数: 
221         //   expression:
222         //     一个标识模型的表达式。
223         //
224         //   viewData:
225         //     视图数据字典。
226         //
227         // 类型参数: 
228         //   TParameter:
229         //     参数的类型。
230         //
231         //   TValue:
232         //     值的类型。
233         //
234         // 返回结果: 
235         //     元数据。
236         public static ModelMetadata FromLambdaExpression<TParameter, TValue>(Expression<Func<TParameter, TValue>> expression, ViewDataDictionary<TParameter> viewData);
237         //
238         // 摘要: 
239         //     从模型的表达式参数中获取元数据。
240         //
241         // 参数: 
242         //   expression:
243         //     一个标识模型的表达式。
244         //
245         //   viewData:
246         //     视图数据字典。
247         //
248         // 返回结果: 
249         //     模型的元数据。
250         public static ModelMetadata FromStringExpression(string expression, ViewDataDictionary viewData);
251         //
252         // 摘要: 
253         //     获取模型的显示名称。
254         //
255         // 返回结果: 
256         //     模型的显示名称。
257         public string GetDisplayName();
258         //
259         // 摘要: 
260         //     返回模型的简单说明。
261         //
262         // 返回结果: 
263         //     模型的简单说明。
264         protected virtual string GetSimpleDisplayText();
265         //
266         // 摘要: 
267         //     获取模型的验证程序的列表。
268         //
269         // 参数: 
270         //   context:
271         //     控制器上下文。
272         //
273         // 返回结果: 
274         //     模型的验证程序的列表。
275         public virtual IEnumerable<ModelValidator> GetValidators(ControllerContext context);
276     }
View Code

 这个类定义了有很多的属性,下面分别分组介绍:

a. 基本属性

1 public Type ContainerType { get; }
2 public virtual bool IsComplexType { get; }
3 public bool IsNullableValueType { get; }
4 public object Model { get; set; }
5 public Type ModelType { get; }
6 public string PropertyName { get; }

  ContainerType表示容器的类型, 对对象类型本身,无类型定义包括它,其ContainerType是null, 其属性的ModelMetadata的ContainerType是对象类型

  IsComplexType表示是否复杂类型, 判断的依据是是否与字符串进行转换, return !(TypeDescriptor.GetConverter(ModelType).CanConvertFrom(typeof(string)); 

  IsNullableValueType 表示是否可空值类型

  Model 表示当前的模型对象

  ModelType 表示Model的类型

  PropertyName 表示属性的名称,对应属性元数据时

 1 protected ModelMetadataProvider Provider { get; set; } 

  表示元数据提供者

1 public virtual Dictionary<string, object> AdditionalValues
2         {
3             get { return _additionalValues; }
4         }

   表示定义的附加的元数据,通过System.Web.Mvc.AdditionalMetadataAttribute实现,该属性实现IMetadataAware接口,在ModelMetadata对象创建后添加元数据到AdditionValues集合。

 b. 定制元数据信息

   1)UIHintAttribute 声明模板名称,对应ModelMetadata的TemplateHint属性

   2)HiddenInputAttribute声明显示为将属性值呈现为hidden元素,同时属性值显示为只读,通过其DisplayValue可隐藏显示,

    对应ModelMetadata两个属性:TemplateHint和HideSurroundingHtml, 注意UIHintAttribute设置具有更高的优先级

   3)ScaffoldColumnAttribute声明元素是否呈现在html中,对应ModelMetadata的ShowForDisplay和ShowForEdit属性

   4)DateTypeAttribute 对应ModelMetadata的DataTypeAttribute

   5)DisplayFormat 对应ModelMetadata的ConvertTEmptyStringToNull, NullDisplayText,DisplayFormatString, EditFormatString

   6)EditableAttribute和ReadonlyAttribute   对应ModelMetadata的IsReadOnly

   7)DisplayAttribute和DisplayNameAttribute   对应ModelMetadata的DisplayName, ShortDisplayName, Description, Order, Watermark

   8)RequiredAttribute 对应ModelMetadata的IsRequired 

        9)AllowHtmlAttribute    对应ModelMetadata的RequestValidationEnabled 

二.元数据提供机制ModelMetadataProvider

    ModelMetadata提供机制是通过ModelMetadataProvider来实现, ModelMetadataProvider是一个抽象类,定义如下:

1 public abstract class ModelMetadataProvider
2     {
3         public abstract IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType);
4 
5         public abstract ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName);
6 
7         public abstract ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType);
8     }
View Code

  在ASP.NET MVC元数据提供入口是ModelMetadataProviders类,实现代码如下:

 1 public class ModelMetadataProviders
 2     {
 3         private static ModelMetadataProviders _instance = new ModelMetadataProviders();
 4         private ModelMetadataProvider _currentProvider;
 5         private IResolver<ModelMetadataProvider> _resolver;
 6 
 7         internal ModelMetadataProviders(IResolver<ModelMetadataProvider> resolver = null)
 8         {
 9             _resolver = resolver ?? new SingleServiceResolver<ModelMetadataProvider>(
10                                         () => _currentProvider,
11                                         new CachedDataAnnotationsModelMetadataProvider(),
12                                         "ModelMetadataProviders.Current");
13         }
14 
15         public static ModelMetadataProvider Current
16         {
17             get { return _instance.CurrentInternal; }
18             set { _instance.CurrentInternal = value; }
19         }
20 
21         internal ModelMetadataProvider CurrentInternal
22         {
23             get { return _resolver.Current; }
24             set { _currentProvider = value ?? new EmptyModelMetadataProvider(); }
25         }
26     }
View Code

  从中我们看到框架默认的元数据提供类型是CachedDataAnnotationsModelMetadataProvider, 整个交互的类图如下:

  

posted @ 2014-05-21 16:03  十三  阅读(520)  评论(0编辑  收藏  举报