一. 元数据描述类型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 modelAccessor, Type modelType, string propertyName); 26 27 // 摘要: 28 // 获取包含有关模型的其他元数据的字典。 29 // 30 // 返回结果: 31 // 包含有关模型的其他元数据的字典。 32 public virtual Dictionary
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.NET123 // MVC 2 Templates, Part 2: ModelMetadata124 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
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
(Expression
> expression, ViewDataDictionary
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
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
AdditionalValues2 {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 ModelMetadataProvider2 {3 public abstract IEnumerable
GetMetadataForProperties(object container, Type containerType);4 5 public abstract ModelMetadata GetMetadataForProperty(Func
modelAccessor, Type containerType, string propertyName);6 7 public abstract ModelMetadata GetMetadataForType(Func 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
_resolver; 6 7 internal ModelMetadataProviders(IResolver
resolver = null) 8 { 9 _resolver = resolver ?? new SingleServiceResolver
(10 () => _currentProvider,11 new CachedDataAnnotationsModelMetadataProvider(),12 "ModelMetadataProviders.Current");13 }14 15 public static ModelMetadataProvider Current16 {17 get { return _instance.CurrentInternal; }18 set { _instance.CurrentInternal = value; }19 }20 21 internal ModelMetadataProvider CurrentInternal22 {23 get { return _resolver.Current; }24 set { _currentProvider = value ?? new EmptyModelMetadataProvider(); }25 }26 }
View Code
从中我们看到框架默认的元数据提供类型是CachedDataAnnotationsModelMetadataProvider, 整个交互的类图如下: