ActionDescriptor 的认识
ActionDescriptor的作用是对Action方法的元数据的描述,通过ActionDescriptor我们可以获取到action方法的相关的名称,所属控制器,方法的参数列表,应用到方法上的特性以及一些筛选器;ActionDescriptor是由ControllerDescriptor类中的FindAction方法进行创建;
ActionDescriptor类也继承了ICustomAttributeProvider接口,所以ActionDescriptor类或是它的继承类也实现了GetCustomAttributes和IsDefined方法;
ActionDescriptor类中的属性和ControllerDescriptor类的属性差不多,包含有一个含有描述操作符唯一性ID的 UniqueId,表示方法名称的ActionName以及action所属于的控制器的元数据描述类ControllerDescriptor等属性字段;为了加快action方法的执行效率,ActionDescriptor类内部还创建了一个action方法调度的缓存属性(ActionMethodDispatcherCache )DispatcherCache;
ActionMethodDispatcherCache 这个类结构是key为MethodInfo value 为ActionMethodDispatcher的字典缓存,在这个缓存类中通过GetDispatcher方法来快速获取ActionMethodDispatcher类;
ReflectedActionDescriptor
ReflectedActionDescriptor类在MVC框架中继承了ActionDescriptor类而且继承了IMethodInfoActionDescriptor接口(获取MethodInfo信息),并且覆盖了一些父类的方法;
在ReflectedActionDescriptor类的构造函数中除了一些基本属性的赋值以外,还会内部调用VerifyActionMethodIsCallable方法来对methodInfo属性进行验证,
VerifyActionMethodIsCallable方法的验证逻辑:
1.方法不是静态函数
2.方法的名称不能是ControllerBase类中的方法
3.泛型方法中不能包含未赋值的泛型类型参数
4.方法的参数中不能有in 或是out修饰的参数
如果验证不通过的话,直接throw一个ArgumentException异常;
在ReflectedActionDescriptor类中包含有一个GetFilterAttributes方法来获取应用到action方法上的FilterAttribute的特性列表;
对于action方法中的参数的元数据的获取是通过GetParameters方法,在ReflectedActionDescriptor类中有一个ParameterDescriptor[]的数组缓存,当缓存中存在时直接从缓存数组中获取相应的参数元数据信息,如果没有则通过MethodInfo的GetParameters方法获取,然后调用ReflectedParameterDescriptor类的构造函数创建参数的元数据信息;
在Control可以存在同名的action方法,当时同名的action方法不能有相同的请求方式,我们可以标记一个action方式支持Post,Get等提交方式,在MVC框架中HttpGetAttribute,HttpPostAttribute等特性类都继承了抽象类ActionMethodSelectorAttribute类,在ActionMethodSelectorAttribute类中只包含一个IsValidForRequest抽象方法
public abstract class ActionMethodSelectorAttribute : Attribute{public abstract bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo);}
在IsValidForRequest 方法目的是验证当前action的方法是否与当前的请求类型相匹配;
在ReflectedActionDescriptor类中提供了获取这些筛选特性的方法GetSelectors,这个方法内部会返回作用于当前action当前的ActionMethodSelectorAttribute类的子类的列表,由于这个返回值是ActionSelector类型的集合,而ActionSelector是一个参数为ControllerContext返回值为布尔类型的委托
public static ICollection<ActionSelector> GetSelectors(MethodInfo methodInfo){ActionMethodSelectorAttribute[] attrs = (ActionMethodSelectorAttribute[])methodInfo.GetCustomAttributes(typeof(ActionMethodSelectorAttribute), inherit: true);ActionSelector[] selectors = Array.ConvertAll(attrs, attr => (ActionSelector)(controllerContext => attr.IsValidForRequest(controllerContext, methodInfo)));return selectors;}
在ReflectedActionDescriptor类中还包含一个和GetSelectors方法类似的内部方法 GetNameSelectors,这个方法返回值为ActionNameSelector类型,这个类型也是一个委托类型,方法的作用是筛选ActionNameSelectorAttribute抽象类的子类的列表;其实内部实现和GetNameSelectors是相似的
public static ICollection<ActionNameSelector> GetNameSelectors(MethodInfo methodInfo){ActionNameSelectorAttribute[] attrs = (ActionNameSelectorAttribute[])methodInfo.GetCustomAttributes(typeof(ActionNameSelectorAttribute), inherit: true);ActionNameSelector[] selectors = Array.ConvertAll(attrs, attr => (ActionNameSelector)((controllerContext, actionName) => attr.IsValidName(controllerContext, actionName, methodInfo)));return selectors;}
对于ActionNameSelectorAttribute与ActionMethodSelectorAttribute类的区别是前者是对action的名字进行筛选,而后者是对请求方式的筛选;
当获得了ReflectedActionDescriptor类后就会执行action方法的执行,对于action方法的执行时直接调用类的Execute方法;
public override object Execute(ControllerContext controllerContext, IDictionary<string, object> parameters)
在Execute方法的内部,由于考虑到性能,避免使用Linq或是委托;
首先通过MethodInfo.GetParameters获取到参数信息列表,然后对参数列表进行遍历验证,参数验证保证不能有重复的参数名,如果参数值为空的话要保证参数的类型是可以为空,当参数值不为空时,要保证参数值的类型和参数的类型一致;如果其中一条规则不符合时就会 throw ArgumentException 异常;
当参数列表遍历完成后,就会在ActionMethodDispatcherCache缓存中通过GetDispatcher方法获取到ActionMethodDispatcher类,然后调用ActionMethodDispatcher类来进行方法的调用,调用完成后执行结果返回;
public override object Execute(ControllerContext controllerContext, IDictionary<string, object> parameters) {if (controllerContext == null){throw new ArgumentNullException("controllerContext");}if (parameters == null){throw new ArgumentNullException("parameters");} // Performance sensitive so avoid Linq or delegates.ParameterInfo[] parameterInfos = MethodInfo.GetParameters();object[] parametersArray = new object[parameterInfos.Length];for (int i = 0; i < parameterInfos.Length; i++){ParameterInfo parameterInfo = parameterInfos[i];object parameter = ExtractParameterFromDictionary(parameterInfo, parameters, MethodInfo);parametersArray[i] = parameter;}ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(MethodInfo);object actionReturnValue = dispatcher.Execute(controllerContext.Controller, parametersArray);return actionReturnValue; }
转载于:https://www.cnblogs.com/h20064528/p/5049052.html
ActionDescriptor 的认识相关推荐
- 控制器描述者(ControllerDescriptor),行为方法描述者(ActionDescriptor),参数描述者(ParameterDescriptor)的小结...
Model的绑定是在Action方法绑定参数时发生的,这个绑定的参数过程要用到的元数据来自于控制器,行为方法和参数的描述者ContrllerDescriptor,ActionDescriptor和Pa ...
- ControllerDescriptor的认识
ControllerDescriptor类主要包含了对ASP.NET MVC中的Control的元数据的解析,在MVC的Model绑定以及数据处理过程中经常会遇到ControllerDescripto ...
- ABP中的Filter(下)
接着上面的一个部分来叙述,这一篇我们来重点看ABP中的AbpUowActionFilter.AbpExceptionFilter.AbpResultFilter这三个部分也是按照之前的思路来一个个介绍 ...
- 判断请求是否为Ajax请求的小妙招
在写后台程序时,有时候需要知道客户端发送的是普通的请求,还是ajax 请求,最近在做项目的时候,有些地方需要判断当前的请求是不是ajax. 概述 在写后台程序时,有时候需要知道客户端发送的是普通的请求 ...
- ASP.NET Web API 过滤器创建、执行过程(二)
ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...
- C#进阶系列——WebApi 身份认证解决方案:Basic基础认证
阅读目录 一.为什么需要身份认证 二.Basic基础认证的原理解析 1.常见的认证方式 2.Basic基础认证原理 三.Basic基础认证的代码示例 1.登录过程 2./Home/Index主界面 3 ...
- Asp.net MVC生命周期
Asp.net应用程序管道处理用户请求时特别强调"时机",对Asp.net生命周期的了解多少直接影响我们写页面和控件的效率.因此在2007年和2008年我在这个话题上各写了一篇文 ...
- ABP源码分析三十四:ABP.Web.Mvc
ABP.Web.Mvc模块主要完成两个任务: 第一,通过自定义的AbpController抽象基类封装ABP核心模块中的功能,以便利的方式提供给我们创建controller使用. 第二,一些常见的基础 ...
- ASP.NET.4.5.1+MVC5.0系统角色和权限讲解
细说ASP.NET.4.5.1+MVC5.0系统角色和权限 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软 ...
最新文章
- (二)数据预处理 2019年研究生数学建模D题《汽车行驶工况构建》
- mall整合SpringBoot+MyBatis搭建基本骨架
- 什么相片可以两张弄成一张_怎么将两张图片合成一张?
- 树莓派+docker+tensorflow
- Linux下进行源码安装时如何避免找不到那些使用--prefix指定目录安装的依赖
- 〖Linux〗VirtualBox修改虚拟电脑硬盘(vdi)空间大小
- Pr 入门教程,如何处理图片文件?
- 软件测试技能大赛山东省,我院获2020年山东省职业院校技能大赛“软件测试”赛项二等奖...
- Vue.js+axios制作的仿酷狗音乐-音乐播放界面
- windows 窗口实现隐藏任务栏预览
- Adobe Photoshop CC 2014图文永久安装教程
- idea启动vue项目
- Tor源码 -- 启动模块
- Android中屏蔽返回键,HOME键以及模拟HOME键返回效果的方法
- 2019年双十一购物数据分析报告
- redis事务java_Redis之Redis的事务
- mysql编码修改utf8_修改数据库mysql字符编码为UTF8
- 在旧时的桃花里,喊疼
- HALCON_根据XLD轮廓 把图像摆正_二
- 关于信息化管理的建议