ASP.NET MVC Model元数据(二)

简介:

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

1
2
3
4
5
6
7
8
9
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类型是比较重要的类型,我们先来看一下它的定义:

1
2
3
4
5
6
7
8
9
10
11
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元数据系列的文章后应该会有所了解,将在后续的篇章中慢慢的揭开它的秘密。谢谢大家的支持。







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





相关文章
|
3月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
42 0
|
1月前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
29 0
|
1月前
mvc.net分页查询案例——mvc-paper.css
mvc.net分页查询案例——mvc-paper.css
5 0
|
1月前
|
开发框架 前端开发 .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,然后在重定向到另
100 5
|
3月前
|
XML 前端开发 定位技术
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
25 0
|
3月前
|
前端开发
.net core mvc获取IP地址和IP所在地(其实是百度的)
.net core mvc获取IP地址和IP所在地(其实是百度的)
124 0
|
8月前
|
存储 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(五)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情等功能的开发,今天继续讲解购物车功能开发,仅供学习分享使用,如有不足之处,还请指正。
117 0
|
5月前
|
开发框架 自然语言处理 前端开发
基于ASP.NET MVC开发的、开源的个人博客系统
基于ASP.NET MVC开发的、开源的个人博客系统
52 0
|
8月前
|
SQL 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(完:内附源码)
经过一段时间的准备,【ASP.NET Core MVC开发实战之商城系统】已经完成,目前代码已开发完成,先将全部内容整理分享,如有不足之处,还请指正。
107 0
|
8月前
|
开发框架 前端开发 .NET
[回馈]ASP.NET Core MVC开发实战之商城系统(六)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情,购物车等功能的开发,今天继续讲解订单管理功能开发,仅供学习分享使用,如有不足之处,还请指正。
215 0