白話學習MVC(五)Controller的激活

1、概述

  在此係列開篇的時候介紹了MVC的生命週期 , 對於請求的處理,都是將相應的類的方法註冊到HttpApplication事件中,經過事件的依次執行從而完成對請求的處理。對於MVC來講,請求是先 通過路由系統,而後由一個MvcHandler來處理的,當請求到來時,執行此MvcHandler的ProcessRequest方法(由於已將 MvcHandler類的ProcessRequest方法註冊到HttpApplication的事件中,因此事件的執行就觸發了此方法)。詳細請看以前介紹MVC生命週期的兩篇博客
  下面咱們就以MVC聲明週期爲主線,來分析下MVC源碼html

public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
{
    protected virtual void ProcessRequest(HttpContext httpContext)
    {
        //使用HttpContextWrapper對HttpContext進行封裝,封裝的目的是爲了解耦以得到可測試性.而後從RequestContext.RouteData中提取Controller名稱.
        HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
        this.ProcessRequest(httpContext2);
    }
    
    protected internal virtual void ProcessRequest(HttpContextBase httpContext)
    {
        IController controller;
        IControllerFactory controllerFactory;
        this.ProcessRequestInit(httpContext, out controller, out controllerFactory);//獲取到Controler和ControllerFactory實例,並賦值給局部變量
        try
        {
          //Action的調用,下一篇介紹
//當前Controler對象的Action的建立與執行(執行包括:加載TempData, 建立及執行Action,處理Action返回的ActionResult ,保存TempData數據) controller.Execute(this.RequestContext); } finally { //釋放當前Controler對象 controllerFactory.ReleaseController(controller); } } }

 

2、Controller的激活

    從上述代碼中能夠看出,對Controller激活的相關的操做是經過MvcHandler類的 ProcessRequestInit 方法來執行,而執行完成後,將獲取到Controller和ControllerFactory實例!也就是說這 個 this.ProcessRequestInit(httpContext, out controller, out controllerFactory) 方法纔是本片博客的旨在,下面就經過這個方法的內部代碼來剖析下Controller的激活的機制!緩存

private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
   //使用指定的 HTTP 上下文來添加版本標頭。如:添加一個Http Header: HTTP/1.1 200 OK   …   X-AspNetMvc-Version: 2.0…
   this.AddVersionHeader(httpContext);
   this.RemoveOptionalRoutingParameters();
//RequestContext.RouteData中提取Controller名稱。如:Home/Index的話,就獲取到Home string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
factory
= this.ControllerBuilder.GetControllerFactory();//獲取一個用於建立Controller實例的ControllerFactory.默認DefaultControllerFactory controller = factory.CreateController(this.RequestContext, requiredString);//根據ControllerFactory建立Controller對象。

if (controller == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture,MvcResources.ControllerBuilder_FactoryReturnedNull,new object[] { factory.GetType(), requiredString })); } } 因爲使用了out關鍵字,這個方法中的執行過程當中所獲得的值,即:賦值給ProcessRequest方法中聲明的Controller和ControllerFactory

 顯然,上述的代碼中這兩行代碼是重點,代碼經過執行一個全局的變量ControllerBuilder的GetControllerFactory方法獲得 一個ControllerFactory,而後再經過執行此ControllerFactory的CreateController方法獲得 Controller實例!mvc

   factory = this.ControllerBuilder.GetControllerFactory();//獲取一個用於建立Controller實例的ControllerFactory.默認DefaultControllerFactory
   controller = factory.CreateController(this.RequestContext, requiredString);//根據ControllerFactory建立Controller對象。

下面就來了解下這兩行代碼:app

一、factory = this.ControllerBuilder.GetControllerFactory();ide

    this.ControllerBuilder是MvcHandler類的一個屬性,屬性返回的是MvcHandler類聲明的一個 ControllerBuilder類型的字段,屬性在返回時會判斷當前字段是否爲空,若是爲空,則調用ControllerBuilder類的靜態屬性 Current字段,來獲取一個ControllerBuilder實例。函數

namespace System.Web.Mvc
{
    public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
    {
        //省略其餘成員變量
        private ControllerBuilder _controllerBuilder;
        internal ControllerBuilder ControllerBuilder
        {
            get
            {
                if (_controllerBuilder == null)
                {
                    _controllerBuilder = ControllerBuilder.Current;
                }
                return _controllerBuilder;
            }
            set { _controllerBuilder = value; }
        }

        private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
        { 
            //省略其餘代碼
            factory = ControllerBuilder.GetControllerFactory();
        }
    }
}
 
_controllerBuilder
= ControllerBuilder.Current;說明ControllerBuilder是由ControllerBuilder類的靜態屬性Current獲取的,接下來再看一下ControllerBuilder類
namespace System.Web.Mvc
{
    public class ControllerBuilder
    {
        //聲明靜態字段,執行此類的構造函數
        private static ControllerBuilder _instance = new ControllerBuilder();

        private Func<IControllerFactory> _factoryThunk = () => null;
        private HashSet<string> _namespaces = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

        //暫且理解爲是封裝ControllerFactory的一個類,經過該類的Current屬性來獲取當前封裝的ControllerFactory實例
        private IResolver<IControllerFactory> _serviceResolver;

        public ControllerBuilder()
            : this(null) //: this(null)表示執行帶一個參數的構造函數,而且傳入的參數爲Null
        {
        }

        internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
        {
            //若是傳入的參數爲null,則實例化一個SingleServiceResolver類並賦值給私有字段_serviceResolver。
            _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
                                                      () => _factoryThunk(),
                                                      new DefaultControllerFactory { ControllerBuilder = this },
                                                      "ControllerBuilder.GetControllerFactory");
        }

        public static ControllerBuilder Current
        {
            //獲取Controller實例
            get { return _instance; }
        }

        public HashSet<string> DefaultNamespaces
        {
            get { return _namespaces; }
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Calling method multiple times might return different objects.")]
        public IControllerFactory GetControllerFactory()
        {
            //獲取ControllerFactory實例
            return _serviceResolver.Current;
        }

        public void SetControllerFactory(IControllerFactory controllerFactory)
        {
            if (controllerFactory == null)
            {
                throw new ArgumentNullException("controllerFactory");
            }

            _factoryThunk = () => controllerFactory;
        }

        public void SetControllerFactory(Type controllerFactoryType)
        {
            if (controllerFactoryType == null)
            {
                throw new ArgumentNullException("controllerFactoryType");
            }
            if (!typeof(IControllerFactory).IsAssignableFrom(controllerFactoryType))
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        MvcResources.ControllerBuilder_MissingIControllerFactory,
                        controllerFactoryType),
                    "controllerFactoryType");
            }

            _factoryThunk = delegate
            {
                try
                {
                    return (IControllerFactory)Activator.CreateInstance(controllerFactoryType);
                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException(
                        String.Format(
                            CultureInfo.CurrentCulture,
                            MvcResources.ControllerBuilder_ErrorCreatingControllerFactory,
                            controllerFactoryType),
                        ex);
                }
            };
        }
    }
}

ControllerBuilder
ControllerBuilder

   ControllerBuilder類中有一個靜態字段private static ControllerBuilder _instance = new ControllerBuilder();,靜態字段是在程序執行前加載的,那麼由代碼可知,就須要執行該類的構造函數,即執行public ControllerBuilder(): this(null),而其後的: this(null)則表示要去執執行帶一個參數的構造函數 ControllerBuilder(IResolver<IControllerFactory> serviceResolver),這個構造函數中首先判斷傳入的參數是否爲空,若是爲空的話就實例化一個 SingleServiceResolver<IControllerFactory>對象(暫且理解爲封裝 ControllerFactory的一個類),並賦值給私有變量_serviceResolver,經過調用_serviceResolver的 Current屬性來獲取當前封裝的ControllerFactory實例。
實例化SingleServiceResolver<IControllerFactory>對象時:學習

public class ControllerBuilder
    {
        //省略其餘成員變量
        private Func<IControllerFactory> _factoryThunk = () => null;       

        internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
        {
            //若是傳入的參數爲null,則實例化一個SingleServiceResolver類並賦值給私有字段_serviceResolver。
            _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
                                                      () => _factoryThunk(),
                                                      new DefaultControllerFactory { ControllerBuilder = this },
                                                      "ControllerBuilder.GetControllerFactory");
        }

        public void SetControllerFactory(IControllerFactory controllerFactory)
        {
            if (controllerFactory == null)
            {
                throw new ArgumentNullException("controllerFactory");
            }

            _factoryThunk = () => controllerFactory;
        }

        public void SetControllerFactory(Type controllerFactoryType)
        {
            //省略其餘代碼
            _factoryThunk = delegate
            {
                try
                {
                    return (IControllerFactory)Activator.CreateInstance(controllerFactoryType);
                }
                catch (Exception ex)
                {
                }
            };
        }
    }

ControllerBuilder
ControllerBuilder

   注意,當實例化SingleServiceResolver<IControllerFactory>時,只有第一個參數是變量,默認狀況 下傳入的是null,那麼實例化的該SingleServiceResolver對象的Current屬性就返回 DefaultControllerFactory;當調用ControllerBuilder的SetControllerFactroy方法時會對_factoryThunk 賦值一個自定義的ControllerFactory時,那麼實例化的該SingleServiceResolver對象的Current屬性就返回自定 義的ControllerFactory。因此,此處就是一個擴展點,咱們能夠自定義一個ControllerFactory,並經過 ControllerBuilder.Current.SetControllerFactory(...)方法來讓程序使用自定的 ControllFatory。這裏須要說明一下的是_factoryThunk 是一個無參數、返回值類型爲IControllerFactory的委託,而_factoryThunk()則是一個執行這個委託獲得的返回值(null、自定義的ControllerFactory)。測試

咱們說了:
  當參數爲null時,該實例對象的Current屬性返回的是DefaultControllerFactory
  當參數爲自定義ControllerBuilder時,該實例對象的Current屬性返回的是自定義的ControllerBuilder
由 於以前咱們一直把SingleServiceResolver<IControllerFactory>看成是一個封裝 ControllerBuilder的一個類,下面就來看看它究竟是不是封裝ControllerBuilder的,而且究竟是如何根據第一個參數的不一樣 而決定其Current屬性返回值的具體類不一樣的。
字體

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;//將此泛型委託賦值給私有變量_currentValueThunk
            _defaultValue = defaultValue;//將此泛型類型賦值給私有變量_defaultValue(當前TService就是IControllerFactory)
            _callerMethodName = callerMethodName;
        }
        
        public TService Current
        {
            //_currentValueThunk()就是第一個參數(無參數的委託)執行以後的返回值
            //_defaultValue就是傳入的DefaultControllerFactory實例
            //可見若是第一個參數爲空的話,返回的就是DefaultControllerFactory實例;不然就是泛型委託的返回值類型的實例,即自定義的ControllerFactory
            get { return _currentValueFromResolver.Value ?? _currentValueThunk() ?? _defaultValue; }
        }
        private TService GetValueFromResolver()
        {
            //_resolverThunk()返回的就是DefaultDependencyResolver實例
            //在調用IDependencyResolver的擴展方法中的GetService<TService>方法
            TService result = _resolverThunk().GetService<TService>();
            return result;
        } }

   若是上述構造函數中的前兩句代碼暫且不議(灰色字體就用不到),那麼就很是簡潔了,即:當構造函數中第一個參數爲null,則 Current的屬性返回的就是第二個參數的值。反映到當前的建立ControllerFacotory,第一個參數就是自定義的 ControllerFactory(可經過ControllerBuilder的SetControllerFactory添加自定義的 ControllerFactory),第二個參數就是默認的DefaultControllerFactory。
  其實,整個過程灰色字體就是經過IService建立實例(此處IService=IControllerFactory),接下來咱們就來單獨的看看被暫且擱置的灰色字體部,分析代碼前,先來了解一下的接口和類:
  IDependencyResolver接口中有兩個方法,是以類型作爲參數經過反射類建立對象,而IDependencyResolver接口還有兩個一樣功能的泛型擴展方法定義在類DependencyResolverExtensions中;
  DefaultDependencyResolver類實現了IDependencyResolver接口;
  DependencyResolver類則是用來建立【實現IDependencyResolver接口的類的實例】,默認狀況建立的是DefaultDependencyResolver類的實例,最終經過DependencyResolver類的靜態Current屬性可獲得建立的實例。
ui

namespace System.Web.Mvc
{
    public class DependencyResolver
    {
        //靜態字段,全部程序開始執行時便會自動執行其構造函數。
        private static DependencyResolver _instance = new DependencyResolver();

        private IDependencyResolver _current;
        private CacheDependencyResolver _currentCache;

        public DependencyResolver()
        {
            InnerSetResolver(new DefaultDependencyResolver());
        }

        public void InnerSetResolver(IDependencyResolver resolver)
        {
            _current = resolver;
        }

        public static IDependencyResolver Current
        {
            get { return _instance.InnerCurrent; }
        }

        public IDependencyResolver InnerCurrent
        {
            get { return _current; }
        }

        //內部私有類
        private class DefaultDependencyResolver : IDependencyResolver
        {
            [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method might throw exceptions whose type we cannot strongly link against; namely, ActivationException from common service locator")]
            public object GetService(Type serviceType)
            {
                if (serviceType.IsInterface || serviceType.IsAbstract)
                {
                    return null;
                }

                try
                {
                    return Activator.CreateInstance(serviceType);
                }
                catch
                {
                    return null;
                }
            }

            public IEnumerable<object> GetServices(Type serviceType)
            {
                return Enumerable.Empty<object>();
            }
        }

    }
}
DependencyResolver
namespace System.Web.Mvc
{
    public interface IDependencyResolver
    {
        object GetService(Type serviceType);
        IEnumerable<object> GetServices(Type serviceType);
    }
}
IDependencyResolver
namespace System.Web.Mvc
{
    //IDependencyResolver的擴展方法
    public static class DependencyResolverExtensions
    {
        public static TService GetService<TService>(this IDependencyResolver resolver)
        {
            return (TService)resolver.GetService(typeof(TService));
        }

        public static IEnumerable<TService> GetServices<TService>(this IDependencyResolver resolver)
        {
            return resolver.GetServices(typeof(TService)).Cast<TService>();
        }
    }
}
DependencyResolverExtensions

  一、_resolverThunk = () => DependencyResolver.Current;
    DependencyResolver類的靜態屬性Current默認狀況下返回的就是一個DependencyResolver實例,並將該實例做爲委託_resolverThunk的返回值。
  二、_currentValueFromResolver = new Lazy<TService>(GetValueFromResolver);

    Lazy表示延遲執行,當執行lazy實例的value屬性時候才執行Lazy構造函數中的方法,方法的返回值就是value屬性的值。此處表示當調用_currentValueFromResolver的value屬性時,就會執行方法GetValueFromResolver(),在方法內調用了執行_resolverThunk委託獲得的DefaultDependencyResolver實例 的擴展方法GetService<TService>經過反射建立TService的實例,並做爲返回值。而方法的返回值就是Lazy的value屬性的值。
  因爲ControllerBuilder構造函數中實例化SingleServiceResolver<TService>類型時,TService=IControllerFactory接口,因此調用泛型方法GetService<TService>()方法時,傳入的類型是接口IControllerFactory,而方法內部的判斷若是是接口或抽象類時候就返回null,即: _currentValueFromResolver.Value=null 。那麼此處的灰色部分執行的最終結果就是_currentValueFromResolver.Value=null,在這裏沒有其到做用!

 

  以 上介紹了factory = this.ControllerBuilder.GetControllerFactory();中的ControllerBuilder如何實例化,並 如何返回一個ControllerFactory實例。有了ControllerFactory以後,那麼就該調用ControllerFactory的 CreateController(RequestContext requestContext, string controllerName);方法(根據第二個參數經過反射實例化一個Controller,並返回)。

// 非重點補充:ControllerBuilder的 DefaultNamespaces屬性

        public HashSet<string> DefaultNamespaces
        {
            get { return _namespaces; }
        }

      //HashSet<T>是一組不重複出現且無特定順序的元素集合
  //此屬性的功能正如其名字DefaultNamespaces,默認的命名空間。即:當存在兩個同名的Controller且命名空間不一樣,這中狀況是容許的,可是MVC在激活Controller時會分不清到底要激活那個Controller,而此屬性的目的就是處理這種狀況的,他能讓MVC激活DefaultNamespaces設置的命名空間下的Controller;除此以外,還有一處能夠解決此問題,那就是路由註冊時的MapRoute方法的參數string[] namespaces 。當二者同時存在時,後者優先。

非重點補充
非重點補充

注:以上所說的ControllerFactory泛指實現了IControllerFactory接口的類;

二、controller = factory.CreateController(this.RequestContext, requiredString);

   此行代碼,利用上一句獲得一個ControllerFactory實例,再將【請求上下文】和【要激活的Controller的字符串】做爲參數來調用 ControllerFactory類的CreateController方法,以此建立Controller實例,並返回!  即:經過ControllerFactory類來完成對Controller的激活,那麼對於此行代碼的解析就成了對ControllerFactory 類的分析!

  由於ControllerFactory泛指實現了IControllerFactory的類,因此就從IControllerFactory接口開始介紹:

    public interface IControllerFactory
    {
        //獲取Controller實例
        IController CreateController(RequestContext requestContext, string controllerName);
        //返回值爲SessionStateBehavior枚舉,表示請求處理過程當中會話狀態支持的模式
        SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);
        //釋放Controller實例
        void ReleaseController(IController controller);
    }
public enum SessionStateBehavior
{
Default,使用默認 ASP.NET 邏輯來肯定請求的會話狀態行爲。
Required,爲請求啓用徹底的讀寫會話狀態行爲。
ReadOnly,爲請求啓用只讀會話狀態。
Disabled 禁用會話狀態。
}

  咱們能夠實現此IControllerFactory接 口,再經過ControllerBuilder.Current.SetControllerBuilder()添加自定義的 ControllerBuilder;而後默認狀況下,MVC使用的是DefaultControllerFactory,接下來就看看 DefaultControllerFactory中是如何實現IControllerFactory接口的。

    public class DefaultControllerFactory : IControllerFactory
    {
        //省略其餘成員
        private IResolver<IControllerActivator> _activatorResolver;
        private IControllerActivator _controllerActivator;
        private ControllerBuilder _controllerBuilder;
       
        public DefaultControllerFactory()
            : this(null, null, null)
        {
        }
        //利用自定義的ControllerActivator時,經過在ControllerBuilder中實例化DefaultControllerFactory時出入自定義ControllerActivator爲參數 public DefaultControllerFactory(IControllerActivator controllerActivator)
            : this(controllerActivator, null, null)
        {
        }

        internal DefaultControllerFactory(IControllerActivator controllerActivator, 
            IResolver<IControllerActivator> activatorResolver, IDependencyResolver dependencyResolver)
        {
            //controllerActivator類纔是最終經過反射建立Controller實例的
            //重點:這裏對判斷controllerActivator的判斷,只有當爲空時才使用默認的DefaultControllerActivator
            //因此,這裏又有一個擴展,經過實現IControllerActivator接口建立自定義ControllerActivator
            //在實例化DefaultControllerFactory時傳入自定義ControllerActivator做爲參數
            if (controllerActivator != null)
            {
                _controllerActivator = controllerActivator;
            }
            else
            {
          //這裏的實例化SingleServiceResolver時,傳入的又是接口,如上講解的SingleServiceResolver類中灰色字體部分沒有起到做用!
//此處第一個參數是個常量且爲null,因此此SingleServiceResolver<>的Current屬性只能返回DefaultControllerActivator實例 _activatorResolver = activatorResolver ?? new SingleServiceResolver<IControllerActivator>( () => null, new DefaultControllerActivator(dependencyResolver), "DefaultControllerFactory constructor"); } } //在ControllerBuilder中實例化DefaultControllerFactory時,賦值。(參見ControllerBuilder類的構造函數) internal ControllerBuilder ControllerBuilder { get { return _controllerBuilder ?? ControllerBuilder.Current; } set { _controllerBuilder = value; } } private IControllerActivator ControllerActivator { get { //當_controllerActivator爲空時,纔去_activatorResolver中獲取DefaultControllerActivator實例做爲ControllerActivator if (_controllerActivator != null) { return _controllerActivator; } _controllerActivator = _activatorResolver.Current; return _controllerActivator; } } public virtual IController CreateController(RequestContext requestContext, string controllerName) { //省略其餘代碼        //根據字符串【類型名】和【上下文中的命名空間】建立Controller的類型 Type controllerType = GetControllerType(requestContext, controllerName); IController controller = GetControllerInstance(requestContext, controllerType);//根據類型建立Controller實例 return controller; } protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) { //省略其餘代碼        //調用ControllerActivator實例的Create經過反射建立實例。默認爲DefaultControllerActivator return ControllerActivator.Create(requestContext, controllerType); } }
private class DefaultControllerActivator : IControllerActivator
        {
            private Func<IDependencyResolver> _resolverThunk;

            public DefaultControllerActivator()
                : this(null)
            {
            }

            public DefaultControllerActivator(IDependencyResolver resolver)
            {
                if (resolver == null)
                {
                    _resolverThunk = () => DependencyResolver.Current;
                }
                else
                {
                    _resolverThunk = () => resolver;
                }
            }

            public IController Create(RequestContext requestContext, Type controllerType)
            {
                try
                {
                    //若是 符號【??】前面的部分爲空,則經過反射建立實例
                    return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
                }
            }
        }

DefaultControllerActivator
DefaultControllerActivator

  上述代碼中註釋部分包含【Controller激活的步驟】和又一擴展點【建立自定ControllerActivator 】,因此略顯混亂。下面咱們就來用文字敘述一下這兩部分:
1、根據ControllerBuilder中實例化DefaultControllerFactory時,利用的是無參數的構造函數,可是此構造函數又帶着三個爲null的參數執行有三個參數的構造函數,因此默認狀況下私有字段_controllerActivator就是null,那麼執行Current來獲取ControllerActivator時,就將DefaultControllerActivator實例賦值給_controllerActivator字段,以後再調用該實例的Create方法,在方法內部利用反射建立Controller實例。
2、正如咱們所知,最後是經過一個ControllerActivator的Create方法,根據參數【請求上下文】【Controller類型】來實現建立Controller實例的。因此,咱們就能夠經過實現IControllerActivator接口來建立自定義的ControllerActivator。建立自定義的ControllerActivator沒問題,那麼
如何使程序去利用自定義的ControllerActivator呢?
  答:
注意DefaultControllerFactory含有三個參數的構造函數,首先會判斷第一個參數c
ontrollerActivator若是不爲空,則將參數賦值給私有變量_controllerActivator。當經過Current獲取當前ControllerActivator時,判斷 私有變量_controllerActivator是否爲空,若是不爲空,則直接返回。由此,咱們就能夠在實例化DefaultControllerFactory時爲第一個參數傳入自定義ControllerActivator實例,即經過實例化含一個參數DefaultControllerFactory構造函數,進而再去執行三個參數的構造函數。
又如何執行DefaultControllerFactory帶一個參數的構造函數並傳入自定義ControllerActivator實例做爲參數呢?
   答:經過在Application_Start方法中經過ControllerBuilder的SetControllerBuilder方法的參數中 傳入new DefaultControllerFactory(new MyControllerActivator())爲參數。即:MyControllerActivator類是實現了 IControllerActivator接口的自定義ControllerActivator

ControllerBuilder controllerBulder = ControllerBuilder.Current;
controllerBulder.SetControllerFactory(new DefaultControllerFactory(new MyControllerActivator()));

 

   以上就是第二句代碼controller = factory.CreateController(this.RequestContext, requiredString);獲取Controller實例的所有,其中又對發現了一個擴展點【自定義ControllerActivator】和如 何讓程序使用自定義的ControllerActivator

 3、Controller的釋放

  由本篇博客概述中的MvcHandler類中,能夠看出在try finally塊的fianlly中經過controllerFactory.ReleaseController(controller); 即:當前ControllerFactory的ReleseController方法來實現釋放,咱們就來看看默認的DefaultControllerFactory中的ReleseController方法

    public class DefaultControllerFactory : IControllerFactory
    {
        //省略其餘成員

        public virtual void ReleaseController(IController controller)
        {
            IDisposable disposable = controller as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
        }
    }

 

以上本篇博客Controller激活的所有內容!!!

 

 

 

 對於Controller激活的相關知識中遺留的問題有:
一、Controller類型的緩存

二、會話狀態行爲的控制

三、DependencyResoolver類(已更新)

若有興趣的話,對於此三部分的問題能夠到Artech的博客MVC系列【How ASP.NET MVC Works】Controller激活部分學習下!

更新  2013-10-19:已在ContrllerBuilder建立ControllerFactory部分添加對DependencyResoolver類的介紹!

相關文章
相關標籤/搜索