ASP.NET MVC Model元数据(三)

简介:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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对象类型。






     本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1429978,如需转载请自行联系原作者







相关文章
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
48 7
|
3月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
75 0
|
4月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
56 0
|
4月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
4月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
145 0
|
前端开发 数据安全/隐私保护
net MVC中的模型绑定、验证以及ModelState
net MVC中的模型绑定、验证以及ModelState 模型绑定 模型绑定应该很容易理解,就是传递过来的数据,创建对应的model并把数据赋予model的属性,这样model的字段就有值了。
1698 0
|
7月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
212 0
|
7月前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
84 0
|
7月前
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
364 5
|
存储 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(五)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情等功能的开发,今天继续讲解购物车功能开发,仅供学习分享使用,如有不足之处,还请指正。
176 0
下一篇
DataWorks