• 深入理解ASP.NET MVC(5)


    系列目录

    回顾

    系列的前4节深入剖析了ASP.NET URL路由机制,以及MVC在此基础上是如何实现Areas机制的,同时涉及到inbound和outbound很多细节部分。第2节中提到MvcRouteHandler是MVC框架的入口,这节开始,从MvcRouteHandler往下说开去。

    Controller的创建过程:Builder和Factory

    MvcRouteHandler的实现仅仅是通过GetHttpHandler方法返回一个MvcHandler实例,MvcHandler从RouteData中获得controller名字负责创建一个ControllerBuilder的实例,并通过ControllerBuilder的GetControllerFactory返回一个IControllerFactory的实例,这个实例就是DefaultControllerFactory,它的 CreateController方法负责创建需要的Controller实例。下面这段代码来自MvcHandler

    1
    2
    3
    4
    5
    // Get the controller type
    string controllerName = RequestContext.RouteData.GetRequiredString("controller");
    // Instantiate the controller and call Execute
    factory = ControllerBuilder.GetControllerFactory();
    controller = factory.CreateController(RequestContext, controllerName);

    DefaultControllerFactory创建Controller分两步:

    1
    2
    Type controllerType = GetControllerType(requestContext, controllerName);
    IController controller = GetControllerInstance(requestContext, controllerType);

    GetControllerInstance最终是这样创建controller的:

    1
    return (IController)Activator.CreateInstance(controllerType);

    这就使得要使用DI设计模式十分困难。好在我们可以重写GetControllerInstance,并应用各种DI。受书中的影响,个人使用的是Ninject

    另外,为了加快GetControllerType方法,DefaultControllerFactory内部运用缓存机制将当前程序和所有引用程序集的类型缓存成哈希表。

    还可以通过如下方法,提供某些名字空间较高的优先级来优化搜索。

    1
    2
    3
    4
    5
    6
    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        ControllerBuilder.Current.DefaultNamespaces.Add("MyApp.Controllers.*");
        ControllerBuilder.Current.DefaultNamespaces.Add("OtherAssembly.MyNamespace.*");
    }

    上面这种设置名字空间的优先级仍然低于在设置路由表时为某个路由指定的名字空间,Areas机制就是靠在设置路由表时指定名字空间实现的,详见深入理解ASP.NET MVC(4)

    也可以在ControllerBuilder层面上替换ControllerFactory:

    1
    2
    3
    4
    5
    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
    }

    Controller的调用:Controller只是普通的.NET类

    MvcHandler依靠ControllerBuilder和IControllerFactory获得Controller的实例后,调用Controller实例的Execute方法,在该方法返回后再调用IControllerFactory的ReleaseController收尾。由此看出Controller的Execute做了所有的事情,看似“功能强大”,其实它只是.NET的普通类, MVC框架赋予其“非凡”的能力:

    所有的Controller只要实现一个接口,IController,接口的定义了Execute方法:

    1
    2
    3
    4
    5
    6
    7
    namespace System.Web.Mvc {
        using System.Web.Routing;
     
        public interface IController {
            void Execute(RequestContext requestContext);
        }
    }

    从接口定义可以看出,当Controller被“调用”的时候,应该负责完成Execute方法,参数RequestContext封装了HttpContext,所以可以像下面这样直接实现一个Controller,同样可以工作:

    1
    2
    3
    4
    5
    6
    7
    public class HelloWorldController : IController 
    {
        public void Execute(RequestContext requestContext)
        {
            requestContext.HttpContext.Response.Write("Hello, world!");
        }
    }

    然而,需要的逻辑和架构远比这个复杂的多,因此MVC框架提供了如下类关系:

    IController->ControllerBase->Controller

    其中ControllerBase实现Execute,Execute在内部调用ExecuteCore,ExecuteCore作为一个抽象方 法,延迟到Controller中实现。ControllerBase只提供了诸如TempData、ViewData等,Controller的 ExecuteCore方法真正invoke了action机制,是action的入口。下面的代码是ExecuteCore的实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    PossiblyLoadTempData();
    try {
        string actionName = RouteData.GetRequiredString("action");
                    if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) {
                        HandleUnknownAction(actionName);
                    }
         }
     finally {
                    PossiblySaveTempData();
                }

    可以看到RouteData在这里又提供了action参数,可以想象InvokeAction方法依靠这个action的名字调用action,并实现诸多验证机制。下节开始讨论action逻辑。

    劳动果实,转载请注明出处:http://www.cnblogs.com/P_Chou/archive/2010/11/20/details-asp-net-mvc-05.html

  • 相关阅读:
    rdb 和 aof
    nginx 遇见问题与解决问题
    linux 每天一个命令
    Consul 集群搭建
    Consul 安装的与启动
    hession RMI 远程调用
    3、使用Lucene实现千度搜索
    1、什么是Lucene,Lucene能干什么
    Tengine笔记2:通过IP、域名、端口实现虚拟主机
    Tengine笔记3:Nginx的反向代理和健康状态检查
  • 原文地址:https://www.cnblogs.com/feng-NET/p/4665293.html
Copyright © 2020-2023  润新知