本篇主要講述MVC處理請求時創(chuàng)建Controller和執(zhí)行Action的完整過程。

創(chuàng)建Controller

先查看MvcHandler中處理請求的方法BeginProcessRequest:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

        protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)

        {

            IController controller;

            IControllerFactory factory;

            ProcessRequestInit(httpContext, out controller, out factory);

            IAsyncController asyncController = controller as IAsyncController;            if (asyncController != null)

            {

                ……

            }            else

            {

                ……

            }

     }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

再查看其中創(chuàng)建Controller的方法ProcessRequestInit

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

        private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)

        {

            HttpContext currentContext = HttpContext.Current;

            ……

            AddVersionHeader(httpContext);

            RemoveOptionalRoutingParameters();            string controllerName = RequestContext.RouteData.GetRequiredString("controller");

            factory = ControllerBuilder.GetControllerFactory();

            controller = factory.CreateController(RequestContext, controllerName);

            ……

        }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

Controller通過ControllerBuilder屬性的方法GetControllerFactory獲取到ControllerFactory對象然后由ControllerFactory創(chuàng)建,ControllerBuilder屬性定義如下。

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

        internal ControllerBuilder ControllerBuilder

        {            get

            {                if (_controllerBuilder == null)

                {

                    _controllerBuilder = ControllerBuilder.Current;

                }                return _controllerBuilder;

            }            set { _controllerBuilder = value; }

        }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 

可知ControllerBuilder默認(rèn)使用ControllerBuilder.Current,查看ControllerBuilder類的代碼:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

        public IControllerFactory GetControllerFactory()

        {            return _serviceResolver.Current;

        }        internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)

        {

            _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>( () => _factoryThunk(),new DefaultControllerFactory { ControllerBuilder = this },   "ControllerBuilder.GetControllerFactory");

        }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

可知默認(rèn)返回的ControllerFactory為DefaultControllerFactory(當(dāng)然我們也可以注冊默認(rèn)的自定義的ControllerFactory),這里我們可繼續(xù)查看DefaultControllerFactory

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

        internal DefaultControllerFactory(……)

        {

            ……

                _activatorResolver = activatorResolver ?? new SingleServiceResolver<IControllerActivator>(

                                                              () => null,                                                              new DefaultControllerActivator(dependencyResolver),                                                              "DefaultControllerFactory constructor");

            }

        }        private IControllerActivator ControllerActivator

        {            get

            {                if (_controllerActivator != null)

                {                    return _controllerActivator;

                }

                _controllerActivator = _activatorResolver.Current;                return _controllerActivator;

            }

        }        public virtual IController CreateController(RequestContext requestContext, string controllerName)

        {

            ……

            Type controllerType = GetControllerType(requestContext, controllerName);

            IController controller = GetControllerInstance(requestContext, controllerType);            return controller;

        }        protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType)

        {

            ……            return ControllerActivator.Create(requestContext, controllerType);

        }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 

可以看到最終Controller由DefaultControllerActivator來創(chuàng)建

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

            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));

                }                catch (Exception ex)

                {                    throw new InvalidOperationException(

                        String.Format(

                            CultureInfo.CurrentCulture,

                            MvcResources.DefaultControllerFactory_ErrorCreatingController,

                            controllerType),

                        ex);

                }

            }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

到此為止Controller就被創(chuàng)建出來了,這里我們看到了DependencyResolver.Current,這是MVC的默認(rèn)注入容器,如果設(shè)置了容器,Controller的創(chuàng)建就可以通過容器(GetService)來完成了,如果未實(shí)現(xiàn)DependencyResolver或DependencyResolver未注冊該Controller則通過反射來創(chuàng)建(使用Activator.CreateInstance,必須存在無參構(gòu)造函數(shù))。

Controller注入

下面來看對框架的第一個擴(kuò)展也是最基本的擴(kuò)展:為框架提供Ioc容器并注冊Controller。對于Ioc容器的起源和作用這里就不多講了。目前Ioc的思想已經(jīng)普遍地應(yīng)用于各種開發(fā)實(shí)踐當(dāng)中了,特別是企業(yè)應(yīng)用開發(fā)中,Spring已經(jīng)是Java開發(fā)事實(shí)上的基礎(chǔ)框架。Asp.net Mvc也深受影響,雖然框架本身沒有提供Ioc容器的實(shí)現(xiàn),但是提供了很方便的擴(kuò)展方式,通過擴(kuò)展我們不僅可以使用容器管理自定義的對象,甚至可以將對象注入到Mvc框架當(dāng)中(簡單的比如對Controller的注入)。因?yàn)镸vc框架默認(rèn)首先通過容器來獲取對象,然后才是框架提供的方式(一般是一種默認(rèn)實(shí)現(xiàn)),在以后的分析中可以看到許多的源碼都可以證實(shí)這一點(diǎn)。

下面我們通過添加Autofac來實(shí)現(xiàn)依賴注入。

首先通過nuget添加Autofac和Autofac.Mvc5的引用。

 

在App_Start目錄下添加Autofac的初始化類如下:

 

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

public class AutofacConfig

{        public static IDependencyResolver GeResolver()

        {            var builder = new ContainerBuilder();

            Registers(builder);

            builder.RegisterControllers(Assembly.GetExecutingAssembly());            return new AutofacDependencyResolver(builder.Build());

        } 

        private static void Registers(ContainerBuilder builder)

        {

 

        }

}

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

然后在Global.asax的Application_Start方法中添加代碼如下:

DependencyResolver.SetResolver(AutofacConfig.GeResolver());

這樣我們就完成了依賴注入(目前只是Controller的注入,當(dāng)然以后可以AutofacConfig 的Registers方法中把我們需要注入的對象注入到Autofac容器中)。關(guān)于依賴注入需要注意的主要有兩點(diǎn):一個是ContainerBuilder的擴(kuò)展方法RegisterControllers,其參數(shù)類型為params Assembly[]可以傳入一個或多個Assembly然后注冊這些Assembly里的Controller,這樣我們就可以將Controller放到不同的工程里;另一個是DependencyResolver.SetResolver,這樣會替換掉默認(rèn)的DependencyResolver實(shí)現(xiàn),我們正是通過這樣把Autofac容器作為了Mvc的容器從而完成依賴注入。

下面通過一個簡單的例子說明Ioc容器的應(yīng)用。首先創(chuàng)建一個簡單的接口及其實(shí)現(xiàn)的類

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

public interface IIocTest

    {        string Say();

    }    public class IocTest: IIocTest

    {        public string Say()

        {            return "IocTest";

        }

}

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

然后再HomeController中添加一個該接口的字段,并創(chuàng)建一個構(gòu)造函數(shù)用于注入(AutoFac默認(rèn)只支持構(gòu)造函數(shù)注入,但也可以開啟屬性注入)。    

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

    private IIocTest iocTestInsatnce;    public HomeController(IIocTest iocTest)

    {

        iocTestInsatnce = iocTest;

    }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

然后再一個Action中調(diào)用接口方法,然后通過ViewBag(或其它方法)將其傳到頁面并顯示,頁面顯示有多種方法,這里直接加到標(biāo)題中:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

    public ActionResult Index()

    {

        ViewBag.iocSays = iocTestInsatnce.Say();        return View();

    }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 

@{

        ViewBag.Title = "Home Page"+ ViewBag.iocSays;

}

然后運(yùn)行程序,查看相應(yīng)頁面的標(biāo)題,驗(yàn)證注入是否成功。

執(zhí)行Action

創(chuàng)建好Controller之后我們再來看Controller是如何執(zhí)行請求的。

首先看ControllerBase,這是所有Controller的基類,查看它的處理方法BeginExecuteCore。

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

        protected virtual IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)

        {

            ……            try

            {                string actionName = GetActionName(RouteData);

                IActionInvoker invoker = ActionInvoker;

                IAsyncActionInvoker asyncInvoker = invoker as IAsyncActionInvoker;                if (asyncInvoker != null)

                {

                    BeginInvokeDelegate<ExecuteCoreState> beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState, ExecuteCoreState innerState)

                    {                        return innerState.AsyncInvoker.BeginInvokeAction(innerState.Controller.ControllerContext, innerState.ActionName, asyncCallback, asyncState);

                    };

                    EndInvokeVoidDelegate<ExecuteCoreState> endDelegate = delegate(IAsyncResult asyncResult, ExecuteCoreState innerState)

                    {                        if (!innerState.AsyncInvoker.EndInvokeAction(asyncResult))

                        {

                            innerState.Controller.HandleUnknownAction(innerState.ActionName);

                        }

                    };

                    ExecuteCoreState executeState = new ExecuteCoreState() { Controller = this, AsyncInvoker = asyncInvoker, ActionName = actionName };                    return AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, executeState, _executeCoreTag);

                }                else

                {

                     ……

                }

            }

            ……

        }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

可以看到Action的執(zhí)行通過ActionInvoker. BeginInvokeAction實(shí)現(xiàn),ActionInvoker的獲取方式如下:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

        protected virtual IActionInvoker CreateActionInvoker()

        {            return Resolver.GetService<IAsyncActionInvoker>() ?? Resolver.GetService<IActionInvoker>() ?? new AsyncControllerActionInvoker();

        }

http://www.cnblogs.com/ssxg/p/7149450.html