即将离职,闲来无事回顾下MVC的源码,到了Controller创建这里,由于流程有点复杂,鉴于自己记性不太好,索性就记录一下吧,方便日后参照。
1 public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState 2 { 3 //... 4 private ControllerBuilder _controllerBuilder; 5 internal ControllerBuilder ControllerBuilder 6 { 7 get 8 { 9 if (_controllerBuilder == null) 10 { 11 _controllerBuilder = ControllerBuilder.Current; 12 } 13 return _controllerBuilder; 14 } 15 set { _controllerBuilder = value; } 16 } 17 //... 18 protected internal virtual void ProcessRequest(HttpContextBase httpContext) 19 { 20 IController controller; 21 IControllerFactory factory; 22 ProcessRequestInit(httpContext, out controller, out factory); 23 24 try 25 { 26 controller.Execute(RequestContext); 27 } 28 finally 29 { 30 factory.ReleaseController(controller); 31 } 32 } 33 34 private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) 35 { 36 // ... 37 // Get the controller type 38 string controllerName = RequestContext.RouteData.GetRequiredString("controller"); 39 40 // Instantiate the controller and call Execute 41 factory = ControllerBuilder.GetControllerFactory(); 42 controller = factory.CreateController(RequestContext, controllerName); 43 //... 44 }
}
简而言之,controller通过实现IControllerFactory的工厂的CreateController()方法创建,而该工厂通过ControllerBuilder.GetControllerFactory()获得,而ControllerBuilder通过ControllerBuilder类型的一个静态属性Current获得,显然Current是ControllerBuilder类型的一个单例。
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>类型。
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的整个创建过程就是这样了。