MVC5 Controller简要创建过程(1):ControllerFactory的创建
即将离职,闲来无事回顾下MVC的源码,到了Controller创建这里,由于流程有点复杂,鉴于自己记性不太好,索性就记录一下吧,方便日后参照。
首先看MvcHandler:
public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
{
//...
private ControllerBuilder _controllerBuilder;
internal ControllerBuilder ControllerBuilder
{
get
{
if (_controllerBuilder == null)
{
_controllerBuilder = ControllerBuilder.Current;
}
return _controllerBuilder;
}
set { _controllerBuilder = value; }
}
//...
protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
IController controller;
IControllerFactory factory;
ProcessRequestInit(httpContext, out controller, out factory);
try
{
controller.Execute(RequestContext);
}
finally
{
factory.ReleaseController(controller);
}
} private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
// ...
// Get the controller type
string controllerName = RequestContext.RouteData.GetRequiredString("controller"); // Instantiate the controller and call Execute
factory = ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(RequestContext, controllerName);
//...
}
}
简而言之,controller通过实现IControllerFactory的工厂的CreateController()方法创建,而该工厂通过ControllerBuilder.GetControllerFactory()获得,而ControllerBuilder通过ControllerBuilder类型的一个静态属性Current获得,显然Current是ControllerBuilder类型的一个单例。
那么来看看ControllerBuidler:
public class ControllerBuilder
{
private static ControllerBuilder _instance = new ControllerBuilder();
private Func<IControllerFactory> _factoryThunk = () => null;
private HashSet<string> _namespaces = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private IResolver<IControllerFactory> _serviceResolver;
public ControllerBuilder()
: this(null)
{
} internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
{
_serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
() => _factoryThunk(),
new DefaultControllerFactory { ControllerBuilder = this },
"ControllerBuilder.GetControllerFactory");
} public static ControllerBuilder Current
{
get { return _instance; }
}
public IControllerFactory GetControllerFactory()
{
return _serviceResolver.Current;
} public void SetControllerFactory(IControllerFactory controllerFactory)
{
if (controllerFactory == null)
{
throw new ArgumentNullException("controllerFactory");
} _factoryThunk = () => controllerFactory;
}
//...
}
GetControllerFactory()方法返回一个IResolver<IControllerFactory>类型实例的Current属性,默认为SingleServiceResolver<IControllerFactory>类型。
以下是SingleServiceResolver<IControllerFactory>的部分实现:
internal class SingleServiceResolver<TService> : IResolver<TService>
where TService : class
{
private Lazy<TService> _currentValueFromResolver;
private Func<TService> _currentValueThunk;
private TService _defaultValue;
private Func<IDependencyResolver> _resolverThunk;
private string _callerMethodName; public SingleServiceResolver(Func<TService> currentValueThunk, TService defaultValue, string callerMethodName)
{
_resolverThunk = () => DependencyResolver.Current;
_currentValueFromResolver = new Lazy<TService>(GetValueFromResolver);
_currentValueThunk = currentValueThunk;
_defaultValue = defaultValue;
_callerMethodName = callerMethodName;
} internal SingleServiceResolver(Func<TService> staticAccessor, TService defaultValue, IDependencyResolver resolver, string callerMethodName)
: this(staticAccessor, defaultValue, callerMethodName)
{
if (resolver != null)
{
_resolverThunk = () => resolver;
}
} public TService Current
{
get { return _currentValueFromResolver.Value ?? _currentValueThunk() ?? _defaultValue; }
} private TService GetValueFromResolver()
{
TService result = _resolverThunk().GetService<TService>(); if (result != null && _currentValueThunk() != null)
{
return result;
}
}
由此可见Current属性返回的值有一个优先级:
优先级最低的是_defaultValue,_defaultValue在构造函数中通过参数传递进来,在之前的CotrollerBuilder中可以看到,这个默认值是一个DefaultFactory类型实例;
次优先级的是对_currentValueThunk委托的调用,也在构造函数中作为参数传递进来,默认返回Null,并且可以通过CotrollerBuilder的SetControllerFactory()方法进行设置;
最高优先级的是一个GetValueFromResolver()方法的返回值,并通过Lazy<>实现延迟执行,GetValueFromResolver()方法内部,首先是对_resolverThunk委托的调用,该委托可通过构造函数的参数传递,否则返回一个DependencyResolver的Current属性,DependencyResolver我们就比较熟悉了,它用于IOC容器的设置和构建,关于它篇幅所限在后面详解吧,该属性返回一个IDependencyResolver类型实例,默认为MVC内部的一个IOC容器DefaultDependencyResolver,由于默认TService类型是一个接口类型,所以DefaultDependencyResolver的GetService()方法默认返回Null。
ControllerFactory的整个创建过程就是这样了。
MVC5 Controller简要创建过程(1):ControllerFactory的创建的更多相关文章
- MVC5 Controller简要创建过程(2):由ControllerFactory创建Controller
上文已经完成了ControllerFactory的创建,接下来就是调用其CreateController()方法创建Controller了. DefaultControllerFactory中Crea ...
- Spring MVC 原理探秘 - 容器的创建过程
1.简介 在上一篇文章中,我向大家介绍了 Spring MVC 是如何处理 HTTP 请求的.Spring MVC 可对外提供服务时,说明其已经处于了就绪状态.再次之前,Spring MVC 需要进行 ...
- windows进程/线程创建过程 --- windows操作系统学习
有了之前的对进程和线程对象的学习的铺垫后,我们现在可以开始学习windows下的进程创建过程了,我将尝试着从源代码的层次来分析在windows下创建一个进程都要涉及到哪些步骤,都要涉及到哪些数据结构. ...
- 0003 - 基于xml的Spring Bean 的创建过程
一.目录 前言 创建 Bean 容器 加载 Bean 定义 创建 Bean Spring Bean 创建过程中的设计模式 总结 二.前言 2.1 Spring 使用配置 ApplicationCont ...
- Android深入理解Context(二)Activity和Service的Context创建过程
前言 上一篇文章我们学习了Context关联类和Application Context的创建过程,这一篇我们接着来学习Activity和Service的Context创建过程.需要注意的是,本篇的知识 ...
- Spring源码解析 – AnnotationConfigApplicationContext容器创建过程
Spring在BeanFactory基础上提供了一些列具体容器的实现,其中AnnotationConfigApplicationContext是一个用来管理注解bean的容器,从AnnotationC ...
- Python之变量的创建过程
Python之变量的创建过程 一.变量创建过程 首先,当我们定义了一个变量name = 'Kwan'的时候,在内存中其实是做了这样一件事: 程序开辟了一块内存空间,将'Kwan'存储进去,再让变量名n ...
- Java对象的创建过程:类的初始化与实例化
一.Java对象创建时机 我们知道,一个对象在可以被使用之前必须要被正确地实例化.在Java代码中,有很多行为可以引起对象的创建,最为直观的一种就是使用new关键字来调用一个类的构造函数显式地创建对象 ...
- .NET/ASP.NET MVC Controller 控制器(IController控制器的创建过程)
阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...
随机推荐
- Android中ListView无法点击
Android中ListView无法点击 转自:http://xqjay19910131-yahoo-cn.iteye.com/blog/1319502 问题描述: ListView中Item加入 ...
- OSCHina技术导向:Java WEB企业门户平台Liferay
Liferay 是一个完整的门户解决方案,基于J2EE的应用,使用了EJB以及JMS等技术,前台界面部分使用Struts MVC 框架,基于XML的portlet配置文件可以自由地动态扩展,使用了We ...
- tty/pts 相关指令
http://unix.stackexchange.com/questions/136662/how-can-we-know-whos-at-the-other-end-of-a-pseudo-ter ...
- java反射 实例
首先介绍几个概念: 1.Java反射的概念 反射含义:可以获取正在运行的Java对象. 2.Java反射的功能 1)可以判断运行时对象所属的类 2)可以判断运行时对象所具有的成员变量和方法 3)通过反 ...
- Android 指定纯色图标的颜色
最近项目用到了系统图标,但是设计师设计的颜色却与系统图标不一样: 如果每张图片都要用Photoshop进行颜色填充势必增加了工作量,而且不灵活,占资源: 例如同一张图片,希望点击的时候改变颜色 ...
- 开源 iOS 项目分类索引大全
GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助 系统基础库 Category/Util sstoolkit 一套Category类型的库,附带很多自定义 ...
- PHP出现Notice: unserialize() [function.unserialize]: Error at offset问题的解决方案
有两个原因(据我所知)会导致这个问题: (1) 字符串本身的问题 (2)字符编码的问题. 你unserialize的字符串的编码和文件本身的编码不一致.将文件编码改成和字符串一样的编码.这种问题比较隐 ...
- Android自己主动化測试之Monkeyrunner用法及实例
眼下android SDK里自带的现成的測试工具有monkey 和 monkeyrunner两个.大家别看这俩兄弟名字相像,但事实上是完全然全不同的两个工具,应用在不同的測试领域.总的来说,monke ...
- (转)flash的Socket通讯沙箱和安全策略问题
一.沙箱和安全策略问题 1.此问题发生在连接时,准确地说是连接前,分别两种情况: 1.本地播放 本地播放时,默认情况下Flash Player将不允许swf访问任何网络. 访问http://www.m ...
- C#整理4——循环语句
一.循环语句 定义:可以反复执行某段代码,直到不满足循环条件为止. 循环的四要素:初始条件.循环条件.状态改变.循环体. 1.初始条件:循环最开始的状态. 2.循环条件:在什么条件下进行循环,不满足 ...