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. opencv在图像显示中文

    在图像定位和模式识别时,经常需要把结果标注到图片上,标注内容可以是数字字母.矩形框等(opencv支持的)或者是中文汉字(借助freetype). 1.显示数字/矩形框 #include <op ...

  2. Java8实战分享

    虽然很多人已经使用了JDK8,看到不少代码,貌似大家对于Java语言or SDK的使用看起来还是停留在7甚至6. Java8在流式 or 链式处理,并发 or 并行方面增强了很多,函数式的风格使代码可 ...

  3. windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...

  4. QT5利用chromium内核与HTML页面交互

    在QT5.4之前,做QT开发浏览器只能选择QWebkit,但是有过使用的都会发现,这个webkit不是出奇的慢,简直是慢的令人发指,Release模式下还行,debug下你就无语了,但是webkit毕 ...

  5. Unity3D框架插件uFrame实践记录(二)

    5.创建属性和命令 本小节主要内容包括: 在Element节点上创建属性数据 在Element节点上创建命令数据 5.1.在Element节点上创建属性数据 在这里,我们首先为Login节点中的属性( ...

  6. ajax请求和aspx返回数据

    ajax请求: $(function () {            $.ajax({                url: "index.aspx?method=send",  ...

  7. dedecms 后台栏目添加图片

    前台调用栏目时需要显示图标,整理一下: 第一步:“系统->SQL命令工具” , 插入sql语句 alter table dede_arctype add typeimg varchar() 第二 ...

  8. CSS常见技巧

    一.CSS Sprite(雪碧图|精灵图)指什么? 有什么作用? CSS雪碧 即CSS Sprite,也有人叫它CSS精灵,是一种CSS图像合并技术,该方法是将小图像和背景图片合并到一张图片上,然后利 ...

  9. Node.js 教程 01 - 简介、安装及配置

    系列目录: Node.js 教程 01 - 简介.安装及配置 Node.js 教程 02 - 经典的Hello World Node.js 教程 03 - 创建HTTP服务器 Node.js 教程 0 ...

  10. T-SQL字符串相加之后被截断的那点事

    本文出处:http://www.cnblogs.com/wy123/p/6217772.html 字符串自身相加, 虽然赋值给了varchar(max)类型的变量,在某些特殊情况下仍然会被“截断”,这 ...