ASP.NET MVC Model元数据(二)

前言

在上篇中,给大家留个对Model元数据的印象,并没有对Model元数据有过多的讲解,而在本篇中也不会对Model元数据的本身来解释,而是针对于它的生成过程,让大家能够清楚的了解到系统框架是在什么时候生成Model元数据的,对于Model元数据生成篇幅初定为两篇,本篇为它的整体的生成过程,下篇则为详细的生成过程并且会对它本身做一个粗略的介绍,希望大家看完能够有所收获

Model元数据

  • 什么是Model元数据?
  • 生成Model元数据的过程【一】
  • 生成Model元数据的过程【二】
  • ModelMetaData的定义、详解
  • Model元数据应用(常用特性应用)-1
  • Model元数据应用(自定义视图模板)-2
  • Model元数据应用(IMetadataAware接口使用)-3

生成Model元数据的过程【一】

还是如前篇说的那样,既然叫Model元数据(Model指的是视图模型)那么肯定跟Model有关系了,而在我们MVC项目中一般是什么时候会对Model进行操作呢?一般情况下都是在通过控制器的行为请求一个视图的时候,而控制器行为的参数即为Model,然后在行为方法中做一些处理然后再传递给视图。然后再根据上篇最后的一个示意图来看,

图1

生成Model元数据的地方已经锁定到了行为方法,想象一下肯定是不可能在行为方法中来生成的,因为那是我们自定义逻辑的地方。那是在什么地方呢?

想必大家看过之前的对过滤器篇幅的介绍,在ASP.NET MVC 过滤器(三)中对行为过滤器的执行过程讲解的时候,中间有提到过模型绑定器,并且说到了系统框架所要使用到的自定义模型绑定器,而使用这个自定义模型绑定器所需要的两个参数是非常重要的,一个是表示当前控制器上下文的对象ControllerContext,另一个则是生成Model元数据的关键,也是调用自定义模型绑定器的关键参数ModelBindingContext类型。看下

图2

而在ModelBindingContext类型中有个重要的属性,即为Model元数据类型ModelMetadata,由此可以知道在我们的控制器行为执行之前,对应控制器行为的Model的Model元数据ModelMetadata类型已经生成了。(这部分内容详见过滤器篇幅)

而它是怎么生成的呢?是通过系统框架中默认提供的提供程序来生成的,是哪些个类型呢?

图3

那我们就先看一下最顶层的基类ModelMetadataProvider的定义:

代码1-1

public abstract class ModelMetadataProvider
{
// 摘要:
// 在派生类中重写时,初始化派生自 System.Web.Mvc.ModelMetadataProvider 类的对象的新实例。
protected ModelMetadataProvider();
public abstract IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType);
public abstract ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName);
public abstract ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType);
}

非常明白的定义,三个抽象方法,这里我们只需先看GetMetadataForType()方法,其它两个暂时不管下篇中会有讲到,因为先看GetMetadataForType()方法呢?因为它是生成ModelMetadata类型的入口,第一个参数暂时忽略,第二个参数嘛很重要了,是ParameterDescriptor类型的ParameterType属性,表示着Model的类型(也就是控制器方法参数的Type类型),现在我们来看下图4

图4

图4中蓝色线条为主要流程,红色线条是在蓝色处理之后执行的流程。

上面说到,入口方法是为抽象方法,那是怎么具体实现的呢,从图4中可以看到是由实现了ModelMetadataProvider的类型AssociatedMetadataProvider类型来进行处理的,从图4可以看到首先是获取一个AttributeList的类型,AttributeList类型表示着从AssociatedMetadataProvider类型GetMetadataForType()方法参数modelType类型上的特性集合,对了AssociatedMetadataProvider类型是比较重要的类型,我们先来看一下它的定义:

public abstract class AssociatedMetadataProvider : ModelMetadataProvider
{
protected AssociatedMetadataProvider();
protected abstract ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName);
protected virtual IEnumerable<Attribute> FilterAttributes(Type containerType, PropertyDescriptor propertyDescriptor, IEnumerable<Attribute> attributes);
public override IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType);
protected virtual ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, PropertyDescriptor propertyDescriptor);
public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName);
public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType);
protected virtual ICustomTypeDescriptor GetTypeDescriptor(Type type);
}

方法有点多,暂时不用管,大多数方法都是用来在递归生成Model元数据的时候使用的(具体的过程会在下篇中讲解)。好了切回主题接着上面的内容来说,AttributeList类型的由来,是通过ModelMetadataProvider的GetTypeDescriptor()方法根据Model的类型(这里暂且先这么理解,等看完下个篇幅就会知道这里也有可能是Model中的属性类型)来生成一个ICustomTypeDescriptor类型(可以想象成这是对于一种对象类型元数据描述对象的抽象定义。读起来有点绕口,但是确实是这么个意思)。而系统会有个默认的自定义实现来实现这个接口类型,我们通过这个默认的实现来获得Model类型的AttributeList类型。

在有了AttributeList类型后,我们就可以调用AssociatedMetadataProvider类型的CreateMetadata()方法来创建Model元数据对象,但是这个CreateMetadata()的定义是抽象的,而真正的实现是由继承了AssociatedMetadataProvider类型的DataAnnotationsModelMetadataProvider类型,由此过后我们生成得到ModelMetadata元数据对象(真正的过程比较繁琐,不然也不会另起一篇专门用来讲解生成的过程),得到了Model元数据对象过后并没有结束,而是继续调用了AssociatedMetadataProvider类型的ApplyMetadataAwareAttributes()方法,并在此方法中,系统框架会调用我们自定义实现了IMetadataAware接口类型的对象,来对Model元数据对象进行个性化修改,并且最后才会真正的返回Model元数据对象。

有可能看到这里有的朋友对Model元数据还是不怎么清楚和了解,朋友们急我也急,如果我分享的这些知识大家看完都不知所云那我又是何必呢。先不要急看了多少就是多少在看完这个Model元数据系列的文章后应该会有所了解,将在后续的篇章中慢慢的揭开它的秘密。谢谢大家的支持。

作者:金源

出处:http://www.cnblogs.com/jin-yuan/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

ASP.NET MVC Model元数据(二)的更多相关文章

  1. ASP.NET MVC Model绑定(二)

    ASP.NET MVC Model绑定(二) 前言 上篇对于Model绑定的简单演示想必大家对Model绑定的使用方式有一点的了解,那大家有没有想过Model绑定器是在什么时候执行的?又或是执行的过程 ...

  2. ASP.NET MVC Model元数据(五)

    ASP.NET MVC Model元数据(五) 前言 在上一篇中我们描述了应用于Model上面的各种用于显示控制的特性类,在本篇中将详细的介绍这些特性类的应用,虽然它们跟Model元数据的直接关系并不 ...

  3. ASP.NET MVC Model元数据(四)

    ASP.NET MVC Model元数据(四) 前言 前面的篇幅讲解了Model元数据生成的过程,并没有对Model元数据生成过程的内部和Model元数据结构的详细解释.看完本篇后将会对Model元数 ...

  4. ASP.NET MVC Model元数据(三)

    ASP.NET MVC Model元数据(三) 前言 在上篇中我们大概的讲解了Model元数据的生成过程,并没有对Model元数据本身和详细的生成过程有所描述,本篇将会对详细的生成过程进行讲解,并且会 ...

  5. ASP.NET MVC Model元数据(一)

    ASP.NET MVC Model元数据(一) 前言 在我初学的时候对Model元数据的概念很模糊,或者说是在大脑中没有它的一个模型,作为小白的我去看网上的一些文章还是两眼一黑啥都看不明白,然后我想退 ...

  6. ASP.NET MVC Model元数据

    ASP.NET MVC Model元数据(三) 前言 在上篇中我们大概的讲解了Model元数据的生成过程,并没有对Model元数据本身和详细的生成过程有所描述,本篇将会对详细的生成过程进行讲解,并且会 ...

  7. ASP.NET MVC Model验证(二)

    ASP.NET MVC Model验证(二) 前言 上篇内容演示了一个简单的Model验证示例,然后在文中提及到Model验证在MVC框架中默认所处的位置在哪?本篇就是来解决这个问题的,并且会描述一下 ...

  8. 【笔记】ASP.NET MVC Model元数据

    问题1:什么叫Model元数据? Model元数据,是针对数据类型的一种描述信息.由于复杂类型(或者说类型嵌套的存在,比如CustomerModel中有一个属性为复杂类型Address)的存在,因此M ...

  9. ASP.NET MVC Model之二模型绑定

    Asp.net mvc中的模型绑定,或许大家经常用,但是具体说他是怎么一回事,可能还是会有些陌生,那么,本文就带你理解模型绑定.为了理解模型绑定,本文会先给出其定义,然后对通过比,来得出使用模型绑定的 ...

随机推荐

  1. HTML5 input元素新的特性

    在HTML5中,<input>元素增加了许多新的属性.方法及控件.本文章分别对这三方面进行介绍. 目录 1. 属性 2. 方法 3. 新控件 1. 属性 <input>元素在H ...

  2. [APUE]标准IO库(上)

    一.流和FILE对象 系统IO都是针对文件描述符,当打开一个文件时,即返回一个文件描述符,然后用该文件描述符来进行下面的操作,而对于标准IO库,它们的操作则是围绕流(stream)进行的. 当打开一个 ...

  3. 23种设计模式--单例模式-Singleton

    一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...

  4. Hibernate中事务声明

    Hibernate中JDBC事务声明,在Hibernate配置文件中加入如下代码,不做声明Hibernate默认就是JDBC事务. 一个JDBC 不能跨越多个数据库. Hibernate中JTA事务声 ...

  5. 敏捷测试模式之Scrum及其实践

    一.    敏捷开发模式简介 敏捷是近年来软件研发领域很火的一个词,采用敏捷开发模式的研发团队是越来越多了,尤其是敏捷模式中的Scrum更是佼佼者大行其道,这表明敏捷模式确有其好处,能给企业带来效率的 ...

  6. java中的内部类总结

    内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类 如同一个人是由大脑.肢体.器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液.跳动) 显然, ...

  7. 使用四元数解决万向节锁(Gimbal Lock)问题

    问题 使用四元数可以解决万向节锁的问题,但是我在实际使用中出现问题:我设计了一个程序,显示一个三维物体,用户可以输入绕zyx三个轴进行旋转的指令,物体进行相应的转动. 由于用户输入的是绕三个轴旋转的角 ...

  8. Struts框架的核心业务

    Struts的核心业务 Struts核心业务有很多,这里主要介绍了比较简单一些的: 请求数据的处理,和数据自动封装,类型自动转换 1.Struts中数据处理 1.1.方式1:直接过去servletap ...

  9. mono中发送邮件并保存本次收件人的地址

    在ios端mono开发中,发送邮件可以选择调用ios原生email程序.有两种方式实现这种功能,一是程序跳转到ipad中email程序,另外一种是将发送邮件的界面在自己应用里弹出. 首先第一种方式的代 ...

  10. Mono 3.2.7发布,JIT和GC进一步改进

    Mono 3.2.7已经发布,带来了很多新特性,如改进的JIT.新的面向LINQ的解释器以及使用了64位原生指令等等. 这是一次主要特性发布,累积了大约5个月的开发工作.看上去大部分改进都是底层的性能 ...