緊跟上一篇文章。通過路由和動作匹配後,最終會得到跟當前請求最匹配的一個ActionDescriptor,然後通過IActionInvoker執行動作。 我們先來看一下IActionInvoker如何得到,代碼如下: 從上面的代碼可以看到,一個IActionInvoker是通過IActionInvok ...
緊跟上一篇文章。通過路由和動作匹配後,最終會得到跟當前請求最匹配的一個ActionDescriptor,然後通過IActionInvoker執行動作。
我們先來看一下IActionInvoker如何得到,代碼如下:
context.Handler = (c) => { var routeData = c.GetRouteData(); //根據actiondescriptor實例化ActionContext對象 var actionContext = new ActionContext(context.HttpContext, routeData, actionDescriptor); if (_actionContextAccessor != null) { _actionContextAccessor.ActionContext = actionContext; } //創建IActionInvoker var invoker = _actionInvokerFactory.CreateInvoker(actionContext); if (invoker == null) { throw new InvalidOperationException( Resources.FormatActionInvokerFactory_CouldNotCreateInvoker( actionDescriptor.DisplayName)); } //執行invoker處理請求 return invoker.InvokeAsync(); };
從上面的代碼可以看到,一個IActionInvoker是通過IActionInvokerFactory創建,框架里該介面實現類是ActionInvokerFactory,該類CreateInvoker方法實現代碼如下:
public IActionInvoker CreateInvoker(ActionContext actionContext) { var context = new ActionInvokerProviderContext(actionContext); foreach (var provider in _actionInvokerProviders) { provider.OnProvidersExecuting(context); } for (var i = _actionInvokerProviders.Length - 1; i >= 0; i--) { _actionInvokerProviders[i].OnProvidersExecuted(context); } return context.Result; }
在方法中,首先實例化一個ActionInvokerProviderContext,然後調用IActionInvokerProvider來設置context.Result,context.Result就是一個IActionInvoker,所以我們跟蹤下框架中IActionInvokerProvider實現類,來看看它裡面是如何工作的。框架中的提供了一個實現類ControllerActionInvokerProvider,在OnProvidersExecuting方法中創建了IActionInvoker對象,代碼如下:
public void OnProvidersExecuting(ActionInvokerProviderContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var actionDescriptor = context.ActionContext.ActionDescriptor as ControllerActionDescriptor; if (actionDescriptor != null) { var controllerContext = new ControllerContext(context.ActionContext); // PERF: These are rarely going to be changed, so let's go copy-on-write. controllerContext.ValueProviderFactories = new CopyOnWriteList<IValueProviderFactory>(_valueProviderFactories); controllerContext.ModelState.MaxAllowedErrors = _maxModelValidationErrors; var cacheState = _controllerActionInvokerCache.GetState(controllerContext); context.Result = new ControllerActionInvoker( _controllerFactory, _argumentBinder, _logger, _diagnosticSource, controllerContext, cacheState.Filters, cacheState.ActionMethodExecutor); } }
從上面的代碼我們可以看到,最終就是實例化了一個ControllerActionInvoker對象,該類構造方法前幾個參數不再介紹了,重點是最後兩個參數,一個是IFilterMetadata[],表示跟當前動作相關聯的過濾器信息集合,一個是ObjectMethodExecutor,從名字上可以看出,這個就是控制器方法的執行器。而這兩個參數來自cacheState,這個對象是通過調用_controllerActionInvokerCache.GetState(controllerContext)得到的,它是一個ControllerActionInvokerState結構體類型,定義如下:
public struct ControllerActionInvokerState { public ControllerActionInvokerState( IFilterMetadata[] filters, ObjectMethodExecutor actionMethodExecutor) { Filters = filters; ActionMethodExecutor = actionMethodExecutor; } //動作過濾器集合 public IFilterMetadata[] Filters { get; } //方法執行器 public ObjectMethodExecutor ActionMethodExecutor { get; set; } }
cacheState創建的過程如下:
public ControllerActionInvokerState GetState(ControllerContext controllerContext)
{
var cache = CurrentCache;
var actionDescriptor = controllerContext.ActionDescriptor;
IFilterMetadata[] filters;
Entry cacheEntry;
if (!cache.Entries.TryGetValue(actionDescriptor, out cacheEntry))
{
var filterFactoryResult = FilterFactory.GetAllFilters(_filterProviders, controllerContext);
filters = filterFactoryResult.Filters;
var executor = ObjectMethodExecutor.Create(
actionDescriptor.MethodInfo,
actionDescriptor.ControllerTypeInfo);
cacheEntry = new Entry(filterFactoryResult.CacheableFilters, executor);
cacheEntry = cache.Entries.GetOrAdd(actionDescriptor, cacheEntry);
}
else
{
// Filter instances from statically defined filter descriptors + from filter providers
filters = FilterFactory.CreateUncachedFilters(_filterProviders, controllerContext, cacheEntry.FilterItems);
}
return new ControllerActionInvokerState(filters, cacheEntry.ActionMethodExecutor);
}
主要看下第10行到第15行代碼。首先通過FilterFactory獲取到跟當前動作相關聯的過濾器信息集合,然後通過ObjectMethodExecutor.Create創建一個ObjectMethodExecutor對象,創建好後進行緩存。
其實到這裡我們已經知道IActionInvokder就是一個ControllerActionInvoker,然後調用該對象的InvokeAsync方法開始動作執行。最新版本實現採用了狀態機(如果概念上錯誤,歡迎大家拍磚指正)的特點,執行時在不同狀態之間進行切換,最終完成處理。而這部分工作就是在Next方法里實現的。方法真正執行實在State.ActionInside狀態時執行,在此狀態下通過調用InvokeActionMethodAsync完成控制器方法的執行,主要代碼如下:
//下麵的代碼就是根據方法返回值類型不同,實現不同的邏輯 var returnType = executor.MethodReturnType; if (returnType == typeof(void)) { executor.Execute(controller, orderedArguments); result = new EmptyResult(); } else if (returnType == typeof(Task)) { await (Task)executor.Execute(controller, orderedArguments); result = new EmptyResult(); } else if (executor.TaskGenericType == typeof(IActionResult)) { result = await (Task<IActionResult>)executor.Execute(controller, orderedArguments); if (result == null) { throw new InvalidOperationException( Resources.FormatActionResult_ActionReturnValueCannotBeNull(typeof(IActionResult))); } } else if (executor.IsTypeAssignableFromIActionResult) { if (_executor.IsMethodAsync) { result = (IActionResult)await _executor.ExecuteAsync(controller, orderedArguments); } else { result = (IActionResult)_executor.Execute(controller, orderedArguments); } if (result == null) { throw new InvalidOperationException( Resources.FormatActionResult_ActionReturnValueCannotBeNull(_executor.TaskGenericType ?? returnType)); } } else if (!executor.IsMethodAsync) { var resultAsObject = executor.Execute(controller, orderedArguments); result = resultAsObject as IActionResult ?? new ObjectResult(resultAsObject) { DeclaredType = returnType, }; } else if (executor.TaskGenericType != null) { var resultAsObject = await executor.ExecuteAsync(controller, orderedArguments); result = resultAsObject as IActionResult ?? new ObjectResult(resultAsObject) { DeclaredType = executor.TaskGenericType, }; } else { // This will be the case for types which have derived from Task and Task<T> or non Task types. throw new InvalidOperationException(Resources.FormatActionExecutor_UnexpectedTaskInstance( executor.MethodInfo.Name, executor.MethodInfo.DeclaringType)); } _result = result; }
無論是哪種返回值類型,都是通過調用executor.Execute完成控制器方法調用,並獲取結果,executor就是上面提到的ObjectMethodExecutor,我們只看下Execute方法實現:
public object Execute(object target, object[] parameters) { return _executor(target, parameters); }
這裡面又是一個_executor,它是一個delegate object ActionExecutor(object target, object[] parameters)委托類型,它是在實例化ObjectMethodInvoker時通過GetExecutor方法創建的,採用的是動態lambda表達式,有了這個委托對象,就可以執行控制器方法了。
方法執行後,會得到方法返回結果,然後進入Result相關狀態流程,直到State.ResultInside狀態時,調用InvokeResultAsync方法執行動作結果,具體代碼如下:
protected async Task InvokeResultAsync(IActionResult result) { var actionContext = _actionContext; _diagnosticSource.BeforeActionResult(actionContext, result); try { await result.ExecuteResultAsync(actionContext); } finally { _diagnosticSource.AfterActionResult(actionContext, result); } }
到這裡一個控制器動作就算執行完了,需要指出的是文章只介紹了主體流程,還有很多其他執行狀態文章中沒提到。