您的位置:首页 > 编程语言 > ASP

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

2016-09-09 20:56 295 查看
        继续上篇的内容。
        如果程序未定义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”,网上有很多详细的介绍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息