代码改变世界

MVC5 Controller简要创建过程(1):ControllerFactory的创建

2015-06-26 11:56  cgs  阅读(1295)  评论(0编辑  收藏  举报

即将离职,闲来无事回顾下MVC的源码,到了Controller创建这里,由于流程有点复杂,鉴于自己记性不太好,索性就记录一下吧,方便日后参照。

首先看MvcHandler:

 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类型的一个单例。

那么来看看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的整个创建过程就是这样了。