分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 运营维护

ASP.NET Core学习总结(3)

发布时间:2023-09-06 01:55责任编辑:董明明关键词:.NET

  我们重点来看看这个InvokeInnerFilterAsync。

 protected override async Task InvokeInnerFilterAsync() ???????{ ???????????var next = State.ActionBegin; ???????????var scope = Scope.Invoker; ???????????var state = (object)null; ???????????var isCompleted = false; ???????????while (!isCompleted) ???????????{ ???????????????await Next(ref next, ref scope, ref state, ref isCompleted); ???????????} ???????}

  似曾相识,它与ResourceInvoker的InvokeFilterPipelineAsync几乎是一模一样的。并且也有一个Next方法,里面也是一个大的switch语句,然后是很多case。

 case State.ActionBegin: ???????????????????{ ???????????????????????var controllerContext = _controllerContext; ???????????????????????_cursor.Reset(); ???????????????????????_instance = _cacheEntry.ControllerFactory(controllerContext); ???????????????????????_arguments = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); ???????????????????????var task = BindArgumentsAsync(); ???????????????????????if (task.Status != TaskStatus.RanToCompletion) ???????????????????????{ ???????????????????????????next = State.ActionNext; ???????????????????????????return task; ???????????????????????} ???????????????????????goto case State.ActionNext; ???????????????????} ???????????????case State.ActionNext: ???????????????????{ ???????????????????????var current = _cursor.GetNextFilter<IActionFilter, IAsyncActionFilter>(); ???????????????????????if (current.FilterAsync != null) ???????????????????????{ ???????????????????????????if (_actionExecutingContext == null) ???????????????????????????{ ???????????????????????????????_actionExecutingContext = new ActionExecutingContext(_controllerContext, _filters, _arguments, _instance); ???????????????????????????} ???????????????????????????state = current.FilterAsync; ???????????????????????????goto case State.ActionAsyncBegin; ???????????????????????} ???????????????????????else if (current.Filter != null) ???????????????????????{ ???????????????????????????if (_actionExecutingContext == null) ???????????????????????????{ ???????????????????????????????_actionExecutingContext = new ActionExecutingContext(_controllerContext, _filters, _arguments, _instance); ???????????????????????????} ???????????????????????????state = current.Filter; ???????????????????????????goto case State.ActionSyncBegin; ???????????????????????} ???????????????????????else ???????????????????????{ ???????????????????????????goto case State.ActionInside; ???????????????????????} ???????????????????} ???????????????case State.ActionAsyncBegin: ???????????????????{ ???????????????????????Debug.Assert(state != null); ???????????????????????Debug.Assert(_actionExecutingContext != null); ???????????????????????var filter = (IAsyncActionFilter)state; ???????????????????????var actionExecutingContext = _actionExecutingContext; ???????????????????????_diagnosticSource.BeforeOnActionExecution(actionExecutingContext, filter); ???????????????????????var task = filter.OnActionExecutionAsync(actionExecutingContext, InvokeNextActionFilterAwaitedAsync); ???????????????????????if (task.Status != TaskStatus.RanToCompletion) ???????????????????????{ ???????????????????????????next = State.ActionAsyncEnd; ???????????????????????????return task; ???????????????????????} ???????????????????????goto case State.ActionAsyncEnd; ???????????????????} ???????????????case State.ActionAsyncEnd: ???????????????????{ ???????????????????????Debug.Assert(state != null); ???????????????????????Debug.Assert(_actionExecutingContext != null); ???????????????????????var filter = (IAsyncActionFilter)state; ???????????????????????if (_actionExecutedContext == null) ???????????????????????{ ???????????????????????????// If we get here then the filter didn‘t call ‘next‘ indicating a short circuit. ???????????????????????????_logger.ActionFilterShortCircuited(filter); ???????????????????????????_actionExecutedContext = new ActionExecutedContext( ???????????????????????????????_controllerContext, ???????????????????????????????_filters, ???????????????????????????????_instance) ???????????????????????????{ ???????????????????????????????Canceled = true, ???????????????????????????????Result = _actionExecutingContext.Result, ???????????????????????????}; ???????????????????????} ???????????????????????_diagnosticSource.AfterOnActionExecution(_actionExecutedContext, filter); ???????????????????????goto case State.ActionEnd; ???????????????????} ???????????????case State.ActionSyncBegin: ???????????????????{ ???????????????????????Debug.Assert(state != null); ???????????????????????Debug.Assert(_actionExecutingContext != null); ???????????????????????var filter = (IActionFilter)state; ???????????????????????var actionExecutingContext = _actionExecutingContext; ???????????????????????_diagnosticSource.BeforeOnActionExecuting(actionExecutingContext, filter); ???????????????????????filter.OnActionExecuting(actionExecutingContext); ???????????????????????_diagnosticSource.AfterOnActionExecuting(actionExecutingContext, filter); ???????????????????????if (actionExecutingContext.Result != null) ???????????????????????{ ???????????????????????????// Short-circuited by setting a result. ???????????????????????????_logger.ActionFilterShortCircuited(filter); ???????????????????????????_actionExecutedContext = new ActionExecutedContext( ???????????????????????????????_actionExecutingContext, ???????????????????????????????_filters, ???????????????????????????????_instance) ???????????????????????????{ ???????????????????????????????Canceled = true, ???????????????????????????????Result = _actionExecutingContext.Result, ???????????????????????????}; ???????????????????????????goto case State.ActionEnd; ???????????????????????} ???????????????????????var task = InvokeNextActionFilterAsync(); ???????????????????????if (task.Status != TaskStatus.RanToCompletion) ???????????????????????{ ???????????????????????????next = State.ActionSyncEnd; ???????????????????????????return task; ???????????????????????} ???????????????????????goto case State.ActionSyncEnd; ???????????????????} ???????????????case State.ActionSyncEnd: ???????????????????{ ???????????????????????Debug.Assert(state != null); ???????????????????????Debug.Assert(_actionExecutingContext != null); ???????????????????????Debug.Assert(_actionExecutedContext != null); ???????????????????????var filter = (IActionFilter)state; ???????????????????????var actionExecutedContext = _actionExecutedContext; ???????????????????????_diagnosticSource.BeforeOnActionExecuted(actionExecutedContext, filter); ???????????????????????filter.OnActionExecuted(actionExecutedContext); ???????????????????????_diagnosticSource.AfterOnActionExecuted(actionExecutedContext, filter); ???????????????????????goto case State.ActionEnd; ???????????????????}

  如果我们查看之前的部分,就会发现。在ResourceInvoker中的动作过滤器部分并没有真正的执行,而是调用了抽象方法InvokeInnerFilterAsync。

 ???case State.ActionBegin: ???????????????????????{ ???????????????????????????var task = InvokeInnerFilterAsync(); ???????????????????????????if (task.Status != TaskStatus.RanToCompletion) ???????????????????????????{ ???????????????????????????????next = State.ActionEnd; ???????????????????????????????return task; ???????????????????????????} ???????????????????????????????goto case State.ActionEnd; ???????????????????????} ???????????????????????case State.ActionEnd: ???????????????????????{ ???????????????????????????if (scope == Scope.Exception) ???????????????????????????{ ???????????????????????????????// If we‘re inside an exception filter, let‘s allow those filters to ‘unwind‘ before ???????????????????????????????// the result. ???????????????????????????????isCompleted = true; ???????????????????????????????return Task.CompletedTask; ???????????????????????????} ???????????????????????????????Debug.Assert(scope == Scope.Invoker || scope == Scope.Resource); ???????????????????????????goto case State.ResultBegin; ???????????????????????}

  也就是说,所有的ActionFilter终归到底是在ControlerActionInvoker中执行的。接着我们来看Next方法的后面部分。

 case State.ActionInside: ???????????????????{ ?????????????????????????//关键在这里 ???????????????????????var task = InvokeActionMethodAsync(); ???????????????????????if (task.Status != TaskStatus.RanToCompletion) ???????????????????????{ ???????????????????????????next = State.ActionEnd; ???????????????????????????return task; ???????????????????????} ???????????????????????goto case State.ActionEnd; ???????????????????} ???????????????case State.ActionEnd: ???????????????????{ ???????????????????????if (scope == Scope.Action) ???????????????????????{ ???????????????????????????if (_actionExecutedContext == null) ???????????????????????????{ ???????????????????????????????_actionExecutedContext = new ActionExecutedContext(_controllerContext, _filters, _instance) ???????????????????????????????{ ???????????????????????????????????Result = _result, ???????????????????????????????}; ???????????????????????????} ???????????????????????????isCompleted = true; ???????????????????????????return Task.CompletedTask; ???????????????????????} ???????????????????????var actionExecutedContext = _actionExecutedContext; ???????????????????????Rethrow(actionExecutedContext); ???????????????????????if (actionExecutedContext != null) ???????????????????????{ ???????????????????????????_result = actionExecutedContext.Result; ???????????????????????} ???????????????????????isCompleted = true; ???????????????????????return Task.CompletedTask; ???????????????????} ???????????????default: ???????????????????throw new InvalidOperationException();

  关键应该是那个InvokeActionMethodAsync方法。

 private async Task InvokeActionMethodAsync() ???????{ ???????????var controllerContext = _controllerContext; ???????????var executor = _cacheEntry.ActionMethodExecutor; ???????????var controller = _instance; ???????????var arguments = _arguments; ???????????var orderedArguments = PrepareArguments(arguments, executor); ???????????var diagnosticSource = _diagnosticSource; ???????????var logger = _logger; ???????????IActionResult result = null; ???????????try ???????????{ ???????????????diagnosticSource.BeforeActionMethod( ???????????????????controllerContext, ???????????????????arguments, ???????????????????controller); ???????????????logger.ActionMethodExecuting(controllerContext, orderedArguments); ?????????????????//关键从这开始 ???????????????var returnType = executor.MethodReturnType; ???????????????if (returnType == typeof(void)) ???????????????{ ???????????????????// Sync method returning void ???????????????????executor.Execute(controller, orderedArguments); ???????????????????result = new EmptyResult(); ???????????????} ???????????????else if (returnType == typeof(Task)) ???????????????{ ???????????????????// Async method returning Task ???????????????????// Avoid extra allocations by calling Execute rather than ExecuteAsync and casting to Task. ???????????????????await (Task)executor.Execute(controller, orderedArguments); ???????????????????result = new EmptyResult(); ???????????????} ???????????????else if (returnType == typeof(Task<IActionResult>)) ???????????????{ ???????????????????// Async method returning Task<IActionResult> ???????????????????// Avoid extra allocations by calling Execute rather than ExecuteAsync and casting to Task<IActionResult>. ???????????????????result = await (Task<IActionResult>)executor.Execute(controller, orderedArguments); ???????????????????if (result == null) ???????????????????{ ???????????????????????throw new InvalidOperationException( ???????????????????????????Resources.FormatActionResult_ActionReturnValueCannotBeNull(typeof(IActionResult))); ???????????????????} ???????????????} ???????????????else if (IsResultIActionResult(executor)) ???????????????{ ???????????????????if (executor.IsMethodAsync) ???????????????????{ ???????????????????????// Async method returning awaitable-of-IActionResult (e.g., Task<ViewResult>) ???????????????????????// We have to use ExecuteAsync because we don‘t know the awaitable‘s type at compile time. ???????????????????????result = (IActionResult)await executor.ExecuteAsync(controller, orderedArguments); ???????????????????} ???????????????????else ???????????????????{ ???????????????????????// Sync method returning IActionResult (e.g., ViewResult) ???????????????????????result = (IActionResult)executor.Execute(controller, orderedArguments); ???????????????????} ???????????????????if (result == null) ???????????????????{ ???????????????????????throw new InvalidOperationException( ???????????????????????????Resources.FormatActionResult_ActionReturnValueCannotBeNull(executor.AsyncResultType ?? returnType)); ???????????????????} ???????????????} ???????????????else if (!executor.IsMethodAsync) ???????????????{ ???????????????????// Sync method returning arbitrary object ???????????????????var resultAsObject = executor.Execute(controller, orderedArguments); ???????????????????result = resultAsObject as IActionResult ?? new ObjectResult(resultAsObject) ???????????????????{ ???????????????????????DeclaredType = returnType, ???????????????????}; ???????????????} ???????????????else if (executor.AsyncResultType == typeof(void)) ???????????????{ ???????????????????// Async method returning awaitable-of-void ???????????????????await executor.ExecuteAsync(controller, orderedArguments); ???????????????????result = new EmptyResult(); ???????????????} ???????????????else ???????????????{ ???????????????????// Async method returning awaitable-of-nonvoid ???????????????????var resultAsObject = await executor.ExecuteAsync(controller, orderedArguments); ???????????????????result = resultAsObject as IActionResult ?? new ObjectResult(resultAsObject) ???????????????????{ ???????????????????????DeclaredType = executor.AsyncResultType, ???????????????????}; ???????????????} ???????????????_result = result; ???????????????logger.ActionMethodExecuted(controllerContext, result); ???????????} ???????????finally ???????????{ ???????????????diagnosticSource.AfterActionMethod( ???????????????????controllerContext, ???????????????????arguments, ???????????????????controllerContext, ???????????????????result); ???????????} ???????}

  上面的方法在于不断判断returnType的类型,根据不同的类型执行不同的操作。不难发现,这些returnType正是我们所写的Action的返回类型。换句话说,executor.Execute执行的正是我们的Action方法。那么,executor又是什么呢?它是一个ObjectMethodExecutor类型的变量。从它构造函数可以看出,它实质上是对一个方法的包装。

private ObjectMethodExecutor(MethodInfo methodInfo, TypeInfo targetTypeInfo, object[] parameterDefaultValues) ???????{ ???????????if (methodInfo == null) ???????????{ ???????????????throw new ArgumentNullException(nameof(methodInfo)); ???????????} ???????????MethodInfo = methodInfo; ???????????MethodParameters = methodInfo.GetParameters(); ???????????TargetTypeInfo = targetTypeInfo; ???????????MethodReturnType = methodInfo.ReturnType; ???????????var isAwaitable = CoercedAwaitableInfo.IsTypeAwaitable(MethodReturnType, out var coercedAwaitableInfo); ???????????IsMethodAsync = isAwaitable; ???????????AsyncResultType = isAwaitable ? coercedAwaitableInfo.AwaitableInfo.ResultType : null; ???????????// Upstream code may prefer to use the sync-executor even for async methods, because if it knows ???????????// that the result is a specific Task<T> where T is known, then it can directly cast to that type ???????????// and await it without the extra heap allocations involved in the _executorAsync code path. ?????????????//看这里 ???????????_executor = GetExecutor(methodInfo, targetTypeInfo); ???????????if (IsMethodAsync) ???????????{ ???????????????_executorAsync = GetExecutorAsync(methodInfo, targetTypeInfo, coercedAwaitableInfo); ???????????} ???????????_parameterDefaultValues = parameterDefaultValues; ???????}
public object Execute(object target, object[] parameters) ???????{ ???????????return _executor(target, parameters); ???????}

  Execute方法也只是委托_executor去执行了。而_executor又是在构造函数中赋值的,下面是GetExecutor方法。

private static MethodExecutor GetExecutor(MethodInfo methodInfo, TypeInfo targetTypeInfo) ???????{ ???????????// Parameters to executor ???????????var targetParameter = Expression.Parameter(typeof(object), "target"); ???????????var parametersParameter = Expression.Parameter(typeof(object[]), "parameters"); ???????????// Build parameter list ???????????var parameters = new List<Expression>(); ???????????var paramInfos = methodInfo.GetParameters(); ???????????for (int i = 0; i < paramInfos.Length; i++) ???????????{ ???????????????var paramInfo = paramInfos[i]; ???????????????var valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i)); ???????????????var valueCast = Expression.Convert(valueObj, paramInfo.ParameterType); ???????????????// valueCast is "(Ti) parameters[i]" ???????????????parameters.Add(valueCast); ???????????} ???????????// Call method ???????????var instanceCast = Expression.Convert(targetParameter, targetTypeInfo.AsType()); ???????????var methodCall = Expression.Call(instanceCast, methodInfo, parameters); ???????????// methodCall is "((Ttarget) target) method((T0) parameters[0], (T1) parameters[1], ...)" ???????????// Create function ???????????if (methodCall.Type == typeof(void)) ???????????{ ???????????????var lambda = Expression.Lambda<VoidMethodExecutor>(methodCall, targetParameter, parametersParameter); ???????????????var voidExecutor = lambda.Compile(); ???????????????return WrapVoidMethod(voidExecutor); ???????????} ???????????else ???????????{ ???????????????// must coerce methodCall to match ActionExecutor signature ???????????????var castMethodCall = Expression.Convert(methodCall, typeof(object)); ???????????????var lambda = Expression.Lambda<MethodExecutor>(castMethodCall, targetParameter, parametersParameter); ???????????????return lambda.Compile(); ???????????} ???????}

  可以看到,上面利用表达式类编译成了委托,并且区分有无返回值的情况。至此,我们已经过了整个MVC框架的流程。现在,让我们再重新梳理一遍。

?   Internet=>Application=>Middleware=>IRourer=>MvcRouterHandler=>ControllerActionInvoker=》ActionFilter

?   网络和应用程序之间,通过HTTP协议交互信息。而在应用程序内部,又有由一系列中间件编译成的委托链。然后是整个MVC的入口点,即路由中间件。其中使用了IRouter的RouteAsync方法匹配路由。而在IRouter的默认实现MvcRouterHandler中又调用了IActionInvoker的InvokeAsync方法。IActionInvoker的默认实现ControllerActionInvoker又继承了ResourceInvoker。在ResourceInvoker中,执行了整个过滤器管道的流程。而动作过滤器和真正的动作方法则是在ControllerActionInvoker中执行的。

ASP.NET Core学习总结(3)

原文地址:https://www.cnblogs.com/xsddxz/p/9059736.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved