mvc源码解读(10)-ParameterDescriptor方法Action方法的参数描述对象
前面两篇文章中我们已经大概的讲解了一下ControllerDescriptor和ActionDescriptor这两个分别对应Controller和Action的描述对象,已经大概的知道他们包含的信息了。这篇文章我们将根据mvc3的源码继续往下看,在ControllerActionInvoker类中的InvokeAction方法中通过FindAction获取到ActionDescriptor之后,直接将代码贴上来吧:
跳过中间的那些代码(稍后补充上),直接看这一句:
IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor); |
GetParameterValues方法具体实现如下:
//数据参数绑定包装类 protected virtual IDictionary<string, object> GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) { Dictionary<string, object> parametersDict = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); ParameterDescriptor[] parameterDescriptors = actionDescriptor.GetParameters(); foreach (ParameterDescriptor parameterDescriptor in parameterDescriptors) { parametersDict[parameterDescriptor.ParameterName] = GetParameterValue(controllerContext, parameterDescriptor); } return parametersDict; } |
我们可以看到红色代码中GetParameters方法就是返回一个ParameterDescriptor对象,而GetParameters我们在讲ActionDescriptor的时候就已经说了一下,它最终调用的是ReflectedActionDescriptor里面的LazilyFetchParametersCollection方法:
private ParameterDescriptor[] LazilyFetchParametersCollection() { return DescriptorUtil.LazilyFetchOrCreateDescriptors<ParameterInfo, ParameterDescriptor>( ref _parametersCache /* cacheLocation */, MethodInfo.GetParameters /* initializer */, parameterInfo => new ReflectedParameterDescriptor(parameterInfo, this) /* converter */); } |
ReflectedParameterDescriptor的构造函数如下:
public ReflectedParameterDescriptor(ParameterInfo parameterInfo, ActionDescriptor actionDescriptor) { ParameterInfo = parameterInfo; _actionDescriptor = actionDescriptor; _bindingInfo = new ReflectedParameterBindingInfo(parameterInfo); } |
这里面同时又涉及到一个ReflectedParameterBindingInfo类,该类的构造函数如下:
public ReflectedParameterBindingInfo(ParameterInfo parameterInfo) { _parameterInfo = parameterInfo; ReadSettingsFromBindAttribute(); } |
ReadSettingsFromBindAttribute方法如下:
private void ReadSettingsFromBindAttribute() { BindAttribute attr = (BindAttribute)Attribute.GetCustomAttribute(_parameterInfo, typeof(BindAttribute)); if (attr == null) {return;} _exclude = new ReadOnlyCollection<string>(AuthorizeAttribute.SplitString(attr.Exclude)); _include = new ReadOnlyCollection<string>(AuthorizeAttribute.SplitString(attr.Include)); _prefix = attr.Prefix; } |
这里涉及到的密封类BindAttribute继承自Attribute,顾名思义就是获取应用在方法参数上的自定义特性。BindAttribute的有如下成员:
public string Exclude { get {return _exclude ?? String.Empty; } set {_exclude = value; _excludeSplit = AuthorizeAttribute.SplitString(value); } } public string Include { get {return _include ?? String.Empty; } set {_include = value;_includeSplit = AuthorizeAttribute.SplitString(value); } } public string Prefix {get;set;} internal static bool IsPropertyAllowed(string propertyName, string[] includeProperties, string[] excludeProperties) { bool includeProperty = (includeProperties == null) || (includeProperties.Length == 0) || includeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase); bool excludeProperty = (excludeProperties != null) && excludeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase); return includeProperty && !excludeProperty; } } |
IsPropertyAllowed方法表示指定的属性是否要用于绑定。因此我们回到ReflectedParameterDescriptor这个类的BindingInfo属性:
private readonly ReflectedParameterBindingInfo _bindingInfo; public override ParameterBindingInfo BindingInfo { |
这样我们可以得知ReflectedParameterDescriptor的BindingInfo的Include、Exclude和Prefix属性对应的就是BindAttribute里面的相关属性。分别表示是否显示自己设置的绑定,不绑定的属性名称,Prefix表示绑定的参数属性的前缀名称。因为参数绑时在请求中数据都是带有类名作为前缀的。再回到上面的ReflectedParameterBindingInfo集成自抽象类ParameterBindingInfo,该类有如下成员:
public abstract class ParameterBindingInfo { public virtual IModelBinder Binder {get {return null;}} public virtual ICollection<string> Exclude {get {return new string[0];}} public virtual ICollection<string> Include {get {return new string[0];}} public virtual string Prefix {get {return null; }} |
属性Exclude,Include和Prefix都被子类ReflectedParameterBindingInfo重写了,我们主要看红色的代码,接口IModelBinder的定义如下:
public interface IModelBinder { object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext); } |
接口里面的BindModel方法就是整个mvc的模型绑定的核心,通过以上分析我们可以知道,无论是ControllerDescriptor,ActionDescriptor还是ParameterDescriptor都是为Model绑定获取前提条件,这个后面我们将详细介绍。
转载于:https://www.cnblogs.com/ghhlyy/archive/2013/02/19/2916509.html
mvc源码解读(10)-ParameterDescriptor方法Action方法的参数描述对象相关推荐
- ASP.NET Core MVC 源码学习:详解 Action 的匹配
前言 在 上一篇 文章中,我们已经学习了 ASP.NET Core MVC 的启动流程,那么 MVC 在启动了之后,当请求到达过来的时候,它是怎么样处理的呢? 又是怎么样把我们的请求准确的传达到我们的 ...
- jpcsp源码解读10:指令的执行
这次要说的是处理器类: public class Processor 主要的成员变量: public CpuState cpu = new CpuState(); public static fina ...
- Vue 源码解读(11)—— render helper
当学习成为了习惯,知识也就变成了常识. 感谢各位的 关注.点赞.收藏和评论. 新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn 文章已收录到 github 仓库 liyongning/b ...
- Requests源码解读
Requests源码解读01-README文件&api模块&session模块 Requests是什么? 为什么要用Requests 源码分析 README文件 api.py get方 ...
- 并发编程之 Executor 线程池原理与源码解读
并发编程之 Executor 线程池原理与源码解读 线程是调度 CPU 资源的最小单位,线程模型分为 KLT 模型与 ULT 模型,JVM使用的是 KLT 模型.java线程与 OS 线程保持 1:1 ...
- asp.net mvc源码分析-Action篇 Action的执行
接着上篇 asp.net mvc源码分析-Action篇 DefaultModelBinder 我们已经获取的了Action的参数,有前面的内容我们知道Action的调用时在ControllerAct ...
- asp.net mvc源码分析-Action篇 DefaultModelBinder
接着上篇 asp.net mvc源码分析-Controller篇 ValueProvider 现在我们来看看ModelBindingContext这个对象. ModelBindingContext b ...
- 【 非线性回归 Logistics-Regression 模块实现与源码解读 深度学习 Pytorch笔记 B站刘二大人(5/10)】
非线性回归 Logistics-Regression 模块实现与源码解读 深度学习 Pytorch笔记 B站刘二大人(5/10) 数学推导 什么是logistics函数 在定义上Logistic函数或 ...
- PTMs:QLoRA技巧的简介、使用方法、论文解读、源码解读之详细攻略
PTMs:QLoRA技巧的简介.使用方法.论文解读.源码解读之详细攻略 目录 QLoRA技巧的简介 1.量化.分页优化器 QLoRA技巧的使用方法 1.安装 2.入
最新文章
- mfc 访问局域网mysql_数据库操作:MFC连接与MYSQL
- tomcat正常启动但是访问 404
- 写脚本时遇到的一些问题+自己的一些简单总结[小白版]
- 打包,并自动安装SQL数据库
- Solr7.2.1环境搭建和配置ik中文分词器
- json在线格式化【推荐】
- IIS启用GZip压缩
- USB引脚定义以及导线的颜色定义
- I.MX6UL核心模块tf卡启动linux的实现
- 计算机专业课程思政优秀案例,【转载】专业课程思政教学案例分享之《专业导论(计算机科学与技术)》...
- 无线路由器(WIFI)经常掉线断网的可能的原因
- iosetup mysql_InnoDB:Error:io_setup()failedwithEAGAIN
- 求几道C++题,不用排版,代码尽量简单,方便理解
- Ubuntu图形界面升级方法
- 复数/复频域计算器介绍(解方程组)
- Optimal Design of Energy-Efficient Multi-User MIMO Systems: Is Massive MIMO the Answer?笔记
- 在Vue中使用数字动画
- 淘宝问大家批量提问方法
- uniapp自定义整包更新与热更新
- Java 8中的Base64编码和解码
热门文章
- Flutter GetX 状态管理 使用入门 程序计数器 (二)
- Flutter RotatedBox 旋转组件
- Leetcode-1155 Number of Dice Rolls With Target Sum(掷骰子的N种方法)
- [剑指offer] 61. 序列化二叉树
- HDU 6446 Tree and Permutation(赛后补题)
- linux下 如何切换到root用户
- Android 注解的使用与注意事项
- MapReduce的基本流程
- Android源码-Logger日志系统
- LeetCode--151. 翻转字符串里的单词(字符串翻转,字符串分割)