Action的执行()
作为Controller基类ControllerBase的Execute方法的核心在于对Action方法本身的执行和作为方法返回的ActionResult的执行两者的执行是通过一个叫做ActionInvoker的组件来完成的
ActionInvoker
同样为ActionInvoker定义了一个接口IactionInvoker如下面的代码片段所示该接口定义了一个唯一的方法InvokeAction用于执行指定名称的Action方法该方法的第一个参数是一个表示基于当前Controller上下文的ControllerContext对象
public interface IActionInvoker
{
void InvokeAction(ControllerContext controllerContext string actionName)
}
ControllerContext类型在真正的ASPNET MVC框架中要复杂一些在这里我们对它进行了简化仅仅将它表示成对当前Controller和请求上下文的封装而这两个要素分别通过如下所示的Controller和RequestContext属性表示
public class ControllerContext
{
public ControllerBase Controller { get; set; }
public RequestContext RequestContext { get; set; }
}
ControllerBase中表示ActionInvoker的同名属性在构造函数中被初始化在Execute方法中通过作为方法参数的RequestContext对象创建ControllerContext对象并通过包含在RequestContext中的RouteData得到目标Action的名称然后将这两者作为参数调用ActionInvoker的InvokeAction方法
从前面给出的关于ControllerBase的定义中可以看到在构造函数中默认创建的ActionInvoker是一个类型为ControllerActionInvoker的对象如下所示的代码片段反映了整个ControllerActionInvoker的定义InvokeAction方法的目的在于实现针对Action方法的执行由于Action方法具有相应的参数在执行Action方法之前必须进行参数的绑定ASPNET MVC将这个机制称为Model的绑定而这又涉及另一个重要的组件ModelBinder
public class ControllerActionInvoker : IActionInvoker
{
public IModelBinder ModelBinder { get; private set; }
public ControllerActionInvoker()
{
thisModelBinder = new DefaultModelBinder()
}
public void InvokeAction(ControllerContext controllerContext
stringactionName)
{
MethodInfo method = controllerContextControllerGetType()GetMethods()
First(m =>stringCompare(actionName mName true) == )
List<object> parameters = new List<object>()
foreach (ParameterInfo parameter in methodGetParameters())
{
parametersAdd(thisModelBinderBindModel(controllerContext
parameterName parameterParameterType))
}
ActionResult actionResult = methodInvoke(controllerContextController
parametersToArray()) as ActionResult;
actionResultExecuteResult(controllerContext)
}
}
ModelBinder
我们为ModelBinder提供了一个简单的定义这与在真正的ASPNET MVC中的同名接口的定义不尽相同如下面的代码片段所示该接口具有唯一的BindModel方法根据ControllerContext和Model名称(在这里实际上是参数名称)和类型得到一个作为参数的对象
public interface IModelBinder
{
object BindModel(ControllerContext controllerContext string modelName
Type modelType)
}
通过前面给出的关于ControllerActionInvoker的定义可以看到在构造函数中默认创建的ModelBinder对象是一个DefaultModelBinder对象由于仅仅是对ASPNET MVC的模拟定义在自定义的DefaultModelBinder中的Model绑定逻辑比ASPNET MVC的DefaultModelBinder要简单得多很多复杂的Model机制并未在我们自定义的DefaultModelBinder体现出来
[] []