带你读开源—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”,网上有很多详细的介绍。
- 带你读开源—ASP.NET_MVC(九)
- 带你读开源—ASP.NET_MVC(一)
- 带你读开源—ASP.NET_MVC(二)
- 带你读开源—ASP.NET_MVC(三)
- 带你读开源—ASP.NET_MVC(四)
- 带你读开源—ASP.NET_MVC(五)
- 带你读开源—ASP.NET_MVC(六)
- 带你读开源—ASP.NET_MVC(七)
- 带你读开源—ASP.NET_MVC(八)
- 带你读开源—ASP.NET_MVC(十)
- 带你读开源—ASP.NET_MVC(十一)
- 带你读开源—ASP.NET_MVC(十二)
- 带你读开源—ASP.NET_MVC(十三)
- 带你读开源—ASP.NET_MVC(十四)
- 带你读开源—ASP.NET_MVC(十五)
- ASP.NET_MVC
- .NET_MVC
- ASP.NET_MVC使用Spring.Net.MVC依赖注入学习笔记
- 字符串转整数
- 项目导入时报错:The import javax.servlet.http.HttpServletRequest cannot be resolved
- 第33篇 IOS一对一apprtc开发及mac命令
- Revit开发之ElementParameterFilter
- Lua中string 字符换行方法
- 带你读开源—ASP.NET_MVC(九)
- 51单片机点亮数码管
- 近期看到的很有意思的文章
- hdoj3711【水】
- 我对多线程的理解
- DFS(深度优先搜索)基本介绍
- 【机房收费系统】结账
- JavaScript 对象&& window
- ajax笔记1--HTTP,HTTPS和HTTP请求概念介绍