带你读开源—ASP.NET_MVC(九)

来源:互联网 发布:vs code php 开发 编辑:程序博客网 时间:2024/06/05 05:02

        继续上篇的内容。

        如果程序未定义Authentication和Authorization这两个过滤器,则执行InvokeActionMethodWithFilters方法以获取ActionResult,继而通过执行InvokeActionResultWithFilters方法来处理ActionResult。从名称可以猜测出,InvokeActionMethodWithFilters方法处理的是IActionFilter,而InvokeActionResultWithFilters方法处理的是IResultFilter。

        我们先看InvokeActionMethodWithFilters方法,在其方法体内发现它调用了InvokeActionMethodFilter方法,跟踪进入,见代码段1,从中可以看出它的功能是:先调用OnActionExecuting方法,再执行一些preContext、postContext等乱七八糟的东东,然后调用OnActionExecuted方法。

    

   internal static ActionExecutedContext InvokeActionMethodFilter(IActionFilterfilter, ActionExecutingContext preContext, Func<ActionExecutedContext>continuation)        {           filter.OnActionExecuting(preContext);           if (preContext.Result != null)           {               return new ActionExecutedContext(preContext,preContext.ActionDescriptor, true /* canceled */, null /* exception */)               {                    Result = preContext.Result               };           }            bool wasError = false;            ActionExecutedContext postContext =null;           try           {               postContext = continuation();           }           catch (ThreadAbortException)           {               // This type of exception occurs as a result of Response.Redirect(), butwe special-case so that               // the filters don't see this as an error.               postContext = new ActionExecutedContext(preContext,preContext.ActionDescriptor, false /* canceled */, null /* exception */);                filter.OnActionExecuted(postContext);               throw;           }           catch (Exception ex)           {               wasError = true;               postContext = new ActionExecutedContext(preContext,preContext.ActionDescriptor, false /* canceled */, ex);               filter.OnActionExecuted(postContext);               if (!postContext.ExceptionHandled)               {                    throw;               }           }           if (!wasError)           {               filter.OnActionExecuted(postContext);           }           return postContext;        }

代码段 1

        我们再看InvokeActionResultWithFilters方法的定义,发现它调用了InvokeActionResultFilterRecursive方法,继续跟踪到InvokeActionResultFilterRecursive方法的定义,见代码段2。

    

    private ResultExecutedContextInvokeActionResultFilterRecursive(IList<IResultFilter> filters, intfilterIndex, ResultExecutingContext preContext, ControllerContextcontrollerContext, ActionResult actionResult)        {           // Performance-sensitive            // For compatbility, the following behavior must be maintained           //   The OnResultExecuting eventsmust fire in forward order           //   The InvokeActionResult mustthen fire           //   The OnResultExecuted eventsmust fire in reverse order           //   Earlier filters can processthe results and exceptions from the handling of later filters           // This is achieved by calling recursively and moving through the filterlist forwards            // If there are no more filters to recurse over, create the main result           if (filterIndex > filters.Count - 1)           {               InvokeActionResult(controllerContext, actionResult);               return new ResultExecutedContext(controllerContext, actionResult,canceled: false, exception: null);           }            // Otherwise process the filters recursively           IResultFilter filter = filters[filterIndex];           filter.OnResultExecuting(preContext);           if (preContext.Cancel)           {               return new ResultExecutedContext(preContext, preContext.Result,canceled: true, exception: null);           }            bool wasError = false;           ResultExecutedContext postContext = null;           try           {               // Use the filters in forward direction               int nextFilterIndex = filterIndex + 1;               postContext = InvokeActionResultFilterRecursive(filters,nextFilterIndex, preContext, controllerContext, actionResult);           }           catch (ThreadAbortException)           {               // This type of exception occurs as a result of Response.Redirect(), butwe special-case so that               // the filters don't see this as an error.                postContext = newResultExecutedContext(preContext, preContext.Result, canceled: false,exception: null);               filter.OnResultExecuted(postContext);               throw;           }           catch (Exception ex)           {                wasError = true;               postContext = new ResultExecutedContext(preContext, preContext.Result,canceled: false, exception: ex);               filter.OnResultExecuted(postContext);               if (!postContext.ExceptionHandled)                {                    throw;               }           }           if (!wasError)           {               filter.OnResultExecuted(postContext);           }           return postContext;        }

代码段 2

        代码段1中的注释比较完备,可以帮助我们理解代码的用意。InvokeActionResultFilterRecursive方法是一个递归方法,根据注释以及对代码进行理解,我们可以梳理出Filter执行的条理:首先检查有没有更多的Filter,没有的话就执行ActionResult;如果还有未处理的Filter,则先执行Filter的OnResultExecuting方法,然后递归调用InvokeActionResultFilterRecursive方法自身,再调用Filter的OnResultExecuted方法。

        从上面介绍的内容可以了解到过滤器执行的先后顺序。对于ActionFilter来说,OnActionExecuting在Action执行之前调用,OnActionExecuted在Action执行之后调用;对于ResultFilter而言,OnResultExecuting发生在ActionResult执行之前,OnResultExecuted发生在ActionResult执行之后。

        好了,我们再回过头来看看MVC预置了哪些过滤器。在源码中找到IFilter的定义(代码段3)。

    publicinterface IFilter    {       bool AllowMultiple { get; }    }


代码段 3

        接着,寻找都有哪些类实现了该接口,IActionFilter、IAuthenticationFilter、IAuthorizationFilter、IExceptionFilter、IOverrideFilter、FilterTracer。擦!这些类又是接口,我们常用的ActionFilter和ResultFilter等过滤器实现了这些接口。

        下面谈一下“依赖注入(DI)”,或者“控制反转(IOC)”。我们都知道在面向对象程序设计过程中,一个重要的思想是要尽量的减少对象之间的耦合关系,从而尽可能的适应变化。解除耦合的一个重要概念就是“接口”,根据“里氏替换原则”,我们要针对抽象编程。我们常说的“依赖”是指一个对象A要想实现其预定的功能,必须要其他对象B的协助,而这里的“其他对象B”应该是一个抽象,即“接口”、“抽象类”或“基类”。这样对象A依赖于一个抽象的B,而不依赖于B的实现细节,当需求发生变化时,对象A的实现不用改变,甚至对象A都不知道B的实现发生了变化,从而有效斩断了对象之间的耦合。当然,接口的实例化有很多专业的工具可以实现,例如NInject等,这些工具又称为“IOC容器”,大家可以百度一下“IOC”,网上有很多详细的介绍。

0 0
原创粉丝点击