前面两篇文章中我们已经大概的讲解了一下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 {
            get {
                return _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方法的参数描述对象相关推荐

  1. ASP.NET Core MVC 源码学习:详解 Action 的匹配

    前言 在 上一篇 文章中,我们已经学习了 ASP.NET Core MVC 的启动流程,那么 MVC 在启动了之后,当请求到达过来的时候,它是怎么样处理的呢? 又是怎么样把我们的请求准确的传达到我们的 ...

  2. jpcsp源码解读10:指令的执行

    这次要说的是处理器类: public class Processor 主要的成员变量: public CpuState cpu = new CpuState(); public static fina ...

  3. Vue 源码解读(11)—— render helper

    当学习成为了习惯,知识也就变成了常识. 感谢各位的 关注.点赞.收藏和评论. 新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn 文章已收录到 github 仓库 liyongning/b ...

  4. Requests源码解读

    Requests源码解读01-README文件&api模块&session模块 Requests是什么? 为什么要用Requests 源码分析 README文件 api.py get方 ...

  5. 并发编程之 Executor 线程池原理与源码解读

    并发编程之 Executor 线程池原理与源码解读 线程是调度 CPU 资源的最小单位,线程模型分为 KLT 模型与 ULT 模型,JVM使用的是 KLT 模型.java线程与 OS 线程保持 1:1 ...

  6. asp.net mvc源码分析-Action篇 Action的执行

    接着上篇 asp.net mvc源码分析-Action篇 DefaultModelBinder 我们已经获取的了Action的参数,有前面的内容我们知道Action的调用时在ControllerAct ...

  7. asp.net mvc源码分析-Action篇 DefaultModelBinder

    接着上篇 asp.net mvc源码分析-Controller篇 ValueProvider 现在我们来看看ModelBindingContext这个对象. ModelBindingContext b ...

  8. 【 非线性回归 Logistics-Regression 模块实现与源码解读 深度学习 Pytorch笔记 B站刘二大人(5/10)】

    非线性回归 Logistics-Regression 模块实现与源码解读 深度学习 Pytorch笔记 B站刘二大人(5/10) 数学推导 什么是logistics函数 在定义上Logistic函数或 ...

  9. PTMs:QLoRA技巧的简介、使用方法、论文解读、源码解读之详细攻略

    PTMs:QLoRA技巧的简介.使用方法.论文解读.源码解读之详细攻略 目录 QLoRA技巧的简介 1.量化.分页优化器 QLoRA技巧的使用方法 1.安装 2.入

最新文章

  1. mfc 访问局域网mysql_数据库操作:MFC连接与MYSQL
  2. tomcat正常启动但是访问 404
  3. 写脚本时遇到的一些问题+自己的一些简单总结[小白版]
  4. 打包,并自动安装SQL数据库
  5. Solr7.2.1环境搭建和配置ik中文分词器
  6. json在线格式化【推荐】
  7. IIS启用GZip压缩
  8. USB引脚定义以及导线的颜色定义
  9. I.MX6UL核心模块tf卡启动linux的实现
  10. 计算机专业课程思政优秀案例,【转载】专业课程思政教学案例分享之《专业导论(计算机科学与技术)》...
  11. 无线路由器(WIFI)经常掉线断网的可能的原因
  12. iosetup mysql_InnoDB:Error:io_setup()failedwithEAGAIN
  13. 求几道C++题,不用排版,代码尽量简单,方便理解
  14. Ubuntu图形界面升级方法
  15. 复数/复频域计算器介绍(解方程组)
  16. Optimal Design of Energy-Efficient Multi-User MIMO Systems: Is Massive MIMO the Answer?笔记
  17. 在Vue中使用数字动画
  18. 淘宝问大家批量提问方法
  19. uniapp自定义整包更新与热更新
  20. Java 8中的Base64编码和解码

热门文章

  1. Flutter GetX 状态管理 使用入门 程序计数器 (二)
  2. Flutter RotatedBox 旋转组件
  3. Leetcode-1155 Number of Dice Rolls With Target Sum(掷骰子的N种方法)
  4. [剑指offer] 61. 序列化二叉树
  5. HDU 6446 Tree and Permutation(赛后补题)
  6. linux下 如何切换到root用户
  7. Android 注解的使用与注意事项
  8. MapReduce的基本流程
  9. Android源码-Logger日志系统
  10. LeetCode--151. 翻转字符串里的单词(字符串翻转,字符串分割)