zoukankan      html  css  js  c++  java
  • 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, 整个交互的类图如下:

      

  • 相关阅读:
    《面向对象编程》c++ primer 第15章
    extern的作用(综合网络)
    C程序内存区域分配(5个段作用)
    鼓舞自己的名言
    快速指数算法 和 求逆元算法
    HP Xeon 55xx上GPU的带宽问题
    Ubuntu12.04 安装ibusfbterm0.9.1
    Win7下读写Ext2/Ext3/Ext4文件系统
    fbv安装 为console添加背景图片
    CentOS6/7安装fcitx4.2.5
  • 原文地址:https://www.cnblogs.com/jjyjjyjjy/p/3734632.html
Copyright © 2011-2022 走看看