现在我们首先来看看ActionInvoker属性的定义吧:
复制代码 代码如下:
public IActionInvoker ActionInvoker {
get {
if (_actionInvoker == null) {
_actionInvoker = CreateActionInvoker();
}
return _actionInvoker;
}
set {
_actionInvoker = value;
}
}
protected virtual IActionInvoker CreateActionInvoker() {
return new ControllerActionInvoker();
}
和TempDataProvider属性定义一样,大家一定要习惯这些代码啊。
而ControllerActionInvoker的定义也很简单,但是这个类却不简单啊。
让我们来看看你InvokeAction的定义吧:
复制代码 代码如下:
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName) {
if (controllerContext == null) {
throw new ArgumentNullException("controllerContext");
}
if (String.IsNullOrEmpty(actionName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
}
ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);
if (actionDescriptor != null) {
FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);
try {
AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
if (authContext.Result != null) {
// the auth filter signaled that we should let it short-circuit the request
InvokeActionResult(controllerContext, authContext.Result);
}
else {
if (controllerContext.Controller.ValidateRequest) {
ValidateRequest(controllerContext);
}
IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
}
}
catch (ThreadAbortException) {
// This type of exception occurs as a result of Response.Redirect(), but we special-case so that
// the filters don't see this as an error.
throw;
}
catch (Exception ex) {
// something blew up, so execute the exception filters
ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
if (!exceptionContext.ExceptionHandled) {
throw;
}
InvokeActionResult(controllerContext, exceptionContext.Result);
}
return true;
}
// notify controller that no method matched
return false;
}
这个方法里面的内容不可能一次讲完的,我们看看 ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
很明显ControllerDescriptor是Controller实例的一个包装类。
复制代码 代码如下:
protected virtual ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext) {
Type controllerType = controllerContext.Controller.GetType();
ControllerDescriptor controllerDescriptor = DescriptorCache.GetDescriptor(controllerType, () => new ReflectedControllerDescriptor(controllerType));
return controllerDescriptor;
}
从这个方法中,我们可以知道实际返回的是一个ReflectedControllerDescriptor实例,它是ControllerDescriptor的子类,DescriptorCache.GetDescriptor(...)好像是从缓存中获取的啊,让我们证实一下吧,先来看看ControllerDescriptorCache的GetDescriptor方法:
复制代码 代码如下:
internal sealed class ControllerDescriptorCache : ReaderWriterCache<Type, ControllerDescriptor> {
public ControllerDescriptor GetDescriptor(Type controllerType, Func<ControllerDescriptor> creator) {
return FetchOrCreateItem(controllerType, creator);
}
}
FetchOrCreateItem方法很简单,从缓存中获取ControllerDescriptor ,如果没有就创建并加入缓存然后在返回,缓存实现方式其实就是一个字典Dictionary<TKey, TValue>。
现在看看ReflectedControllerDescriptor的够着函数是否有什么特别之处:
_controllerType = controllerType;
_selector = new ActionMethodSelector(_controllerType);
怎么又有ActionMethodSelector这个东东啊,其构造函数如下
复制代码 代码如下:
public ActionMethodSelector(Type controllerType) {
ControllerType = controllerType;
PopulateLookupTables();
}
private void PopulateLookupTables() {
MethodInfo[] allMethods = ControllerType.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public);
MethodInfo[] actionMethods = Array.FindAll(allMethods, IsValidActionMethod);
AliasedMethods = Array.FindAll(actionMethods, IsMethodDecoratedWithAliasingAttribute);
NonAliasedMethods = actionMethods.Except(AliasedMethods).ToLookup(method => method.Name, StringComparer.OrdinalIgnoreCase);
}
这个方法很简单,找出ControllerType的所有实例、共有方法,然后在过滤调不是Action的,最后吧这些Action方法分成两部分,一部分有别名,一部分没有别名。
现在我们已经得到了ControllerDescriptor实例,下面应该来看看ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName);这句代码了;同样我们可以确认ActionDescriptor实际上一个Action的包装类。
protected virtual ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)这个方法实际上就是调用
ControllerDescriptor类FindAction方法,让我们看看你ReflectedControllerDescriptor的FindAction方法,该方法很简单,组要就2句代码:
复制代码 代码如下: