ASP.NET MVC Model元数据(三)

前言

在上篇中我们大概的讲解了Model元数据的生成过程,并没有对Model元数据本身和详细的生成过程有所描述,本篇将会对详细的生成过程进行讲解,并且会对Model元数据本身的结构稍作讲解,读完本篇过后你将会对Model元数据的结构有个很清晰的印象。

Model元数据

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

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

还记得Model元数据系列篇的第一章里的最后一幅图吗?

图1

没有错,MVC框架根据我们定义的视图模型生成了一个Model元数据ModelMetadata(实际为DataAnnotationsModelMetadata类型是继承自ModelMetadata类型的,在下文中为了更直观的方便讲解所以还是用ModelMetadata类型来作介绍)。我们来看一下ModelMetadata类型的定义:

代码1-1

public class ModelMetadata
{ public ModelMetadata(ModelMetadataProvider provider, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName);
//
// 摘要:
// 获取模型元数据对象的集合,这些对象描述模型的属性。
//
// 返回结果:
// 用于描述模型属性的模型元数据对象的集合。
public virtual IEnumerable<ModelMetadata> Properties { get; }
//
// 摘要:
// 获取模型的类型。
//
// 返回结果:
// 模型的类型。
public Type ModelType { get; }
protected ModelMetadataProvider Provider { get; set; }
……
}

只留了个构造函数和三个属性,详细的部分下篇会讲到,构造函数中的第一个参数类型大家肯定很熟悉,那就是上篇中讲到的Model元数据生成程序,用来生成Model元数据(ModelMetadata类型)的,这样的是把ModelMetadataProvider类型的引用设置到Model元数据的内部,也就是Provider属性,这样做是有目的的随后就会讲到,在其定义中还有个Properties属性,类型大家都看到了是ModelMetadata类型的集合,这就是ModelMetadata类型关键的所在了,Properties属性表示着当前ModelMetadata的所描述类型中的属性元数据集合。

图2

用前篇介绍过的Customer类型来做描述,对应着Customer类型的结构MVC框架也会生成对应的ModelMetadata类型结构,这里捎带提一下,对于Address属性类型是Address类型这种属于复杂类型,MVC框架会向下继续生成就如同生成Customer类型一样。

那么这样的结构是怎么生成的呢?当然不用说了,是依靠Provider属性也就是ModelMetadataProvider类型的引用来生成结构的,如图3所示:

图3

首先根据当前Model元数据ModelMetadata类型(对应的对象是Customer类型)中的Model属性和ModelType属性来作为参数调用AssociatedMetadataProvider类型的GetMetadataForProperties()方法,这里说一下ModelMetadata类型的Model属性,表示着当前Model元数据所对应对象的值,也是用这个值来判断是否是复杂类型的,ModelType属性上面说过。

在GetMetadataForProperties()方法中会先根据自定义类型描述类型的GetProperties()方法来获取当前对象是Customer类型的所有的属性,并且封装成属性描述类型集合。

随后根据获取到的属性描述类型集合,遍历此集合并且根据遍历中的单个属性描述类型调用AssociatedMetadataProvider类型中的GetMetadataForProperty()方法,这里要说的是第一个参数modelAccessor默认是Null的,第二个参数containerType是表示着当前Customer类型,第三个参数就是属性描述类型了里面包含着属性类型的所有信息。有的朋友会问说明这些属性做什么,因为等下会说到第二个参数containerType的。

在AssociatedMetadataProvider类型中的GetMetadataForProperty()方法中,会根据PropertyDescriptor类型的参数获取到当前属性上所有描述信息(也就是那些特性类),比如当前的PropertyDescriptor类型是结构化Customer类型中的CustomerID,那图3中AttrbuteList类型中就是包含着所有依附在这个属性上的特性类。后续的生成过程还是跟上篇的讲解的一样依旧的调用了AssociatedMetadataProvider类型的CreateMetadata(),只不过在AssociatedMetadataProvider类型中方法是抽象中,实际是由它的实现类DataAnnotationsModelMetadataProvider中的CreateMetadata()方法来完成的。

这里大家可能会发现,在图3中黄色框中的操作都是属于遍历中的操作,就是每次都会只会生成一个ModelMetadata类型实例然后最后合并在一起返回出去。

还有要说的就是在图3中黄色框中的每个调用的函数都有个Type类型的containerType参数,这就是上面说过的Customer类型,并且在生成的ModelMetadata类型实例中赋值到ContainerType属性,表示着新生成的ModelMetadata类型实例比如叫A,A中描述的信息就是Customer类型中的CustomerID属性的所有信息,而A中的ContainerType属性就是表示描述的CustomerID属性是属于哪个类型的。

这里还有要说的,就是在系统默认生成的时候,比如说视图模型是Customer类型,那么MVC框架只会生成一个ModelMetadata类型的实例假使它叫M,因为M自身并没有自己检测自己是不是复杂类型,所以M是不会调用提供器往下生成的,而是在外部要使用M了才会去调用M中的函数检测M是不是复杂类型然后往下生成,假使现在MVC框架中使用到了这个M可能就会调用检测它自身的方法来检查它是不是复杂类型,明显的Customer类型是复杂类型,这个时候M会按照本篇描述的那样依次的生成它所描述类型中的属性,也只是仅限于这一层,有的朋友可能会问在Customer类型中Address属性也是复杂类型,对的,但是M只会去生成Address属性本身的ModelMetadata类型的实例,而不会去生成Address属性的内部。

现在大家再看一次图2,是不是有点清晰的感觉。

(有哪位大神知道在MVC框架中是在哪里调用ModelMetadata类型实例的自身检测的?知道的告知一下小弟以身相许,找的头破血流也没找到,我相信是肯定有的)

本篇结束,下篇中详细介绍DataAnnotationsModelMetadataProvider类型中的CreateMetadata()方法,从这个方法进入,详细的讲解ModelMetadata对象类型。

作者:金源

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

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

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

  1. ASP.NET MVC Model元数据

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

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

    ASP.NET MVC Model元数据(二) 前言 在上篇中,给大家留个对Model元数据的印象,并没有对Model元数据有过多的讲解,而在本篇中也不会对Model元数据的本身来解释,而是针对于它的 ...

  3. ASP.NET MVC Model验证(三)

    ASP.NET MVC Model验证(三) 前言 上篇中说到在MVC框架中默认的Model验证是在哪里验证的,还讲到DefaultModelBinder类型的内部执行的示意图,让大家可以看到默认的M ...

  4. ASP.NET MVC Model绑定(三)

    ASP.NET MVC Model绑定(三) 前言 看过前两篇的朋友想必对Model绑定有个大概的了解,然而MVC框架给我们提供了更高的可扩展性的提供程序编程模式,也就是本篇的主题了,会讲解一下Mod ...

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

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

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

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

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

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

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

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

  9. ASP.NET MVC Model验证(四)

    ASP.NET MVC Model验证(四) 前言 本篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现,前者是Model验证提供程序,而Mod ...

随机推荐

  1. .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]

    构造函数.析构函数 构造函数: 语法: //无参的构造函数 [访问修饰符] 函数名() :函数名必须与类名相同. //有参的构造函数 [访问修饰符] 函数名(参数列表):函数名必须与类名相同. 作用: ...

  2. SQL Server-聚焦计算列或计算列持久化查询性能(二十二)

    前言 上一节我们详细讲解了计算列以及计算列持久化的问题,本节我们依然如前面讲解来看看二者查询性能问题,简短的内容,深入的理解,Always to review the basics. 持久化计算列比非 ...

  3. CRL快速开发框架系列教程十一(大数据分库分表解决方案)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  4. PHP与API讲解(一)

    了解API: 在使用与创建自己的API之前我们需要先了解什么是API! API代表应用程序编程接口,而接口指的是一个特定的服务.一个应用程序或者其他程序的公共模块. 理解SOA(面向服务的架构):SO ...

  5. 就这么漂来漂去---一个毕业三个月的java程序员的裸辞风波

    注:这并不是一篇技术文章,而是记录了我这几个月经历的入职,裸辞,找工作的心路历程,简单介绍一个博主的情况,我是16年毕业生,校招进了一家北京的公司,java开发,和很多年轻人一样,干了一段时间,我发现 ...

  6. node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法

    1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...

  7. WPF 普通属性变化通知

    问题描述:使用ObservableCollection<OrderItem> source 给Datagrid.ItemsSource赋值,在后台更新source集合后,前台Datagri ...

  8. gulp批量打包文件并提取公共文件

    gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器. browseriyf是模块化打包工具. 一般情况下,Browserify 会把所有的模块打包成单个文件.单个文件在大多数情况下是 ...

  9. 如何为你的微信小程序体积瘦身?

    众所周知,微信小程序在发布的时候,对提交的代码有1M大小的限制!所以,如果你正在写一个功能稍微复杂一点的小程序,就必须得时刻小心注意你的代码是不是快触及这个底线了. 在设计一个小程序之初,我们就需要重 ...

  10. Android—万能ListView适配器

    ListView是开发中最常用的控件了,但是总是会写重复的代码,浪费时间又没有意义. 最近参考一些资料,发现一个万能ListView适配器,代码量少,节省时间,总结一下分享给大家. 首先有一个自定义的 ...