带你读开源—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”,网上有很多详细的介绍。
如果程序未定义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 1.0 项目
- 一起谈.NET技术,ASP.NET MVC 3 Beta新特性以及.Net开源的趋势----最新译文
- [ASP.NET MVC 3 系列] ASP.NET MVC 3 Beta新特性以及.Net开源的趋势----最新译文
- 推荐一款asp.net-MVC开源框架,完全开源免费使用
- asp.net mvc相关开源项目推荐
- asp.net mvc相关开源项目推荐
- Asp.net MVC 2.0 + Unity 2.0(IoC) + EF4.0 实例:RoRoWoBlog 开源项目框架代码
- 【转载】使用Json比用string返回数据更友好,也更面向对象一些 |Asp.net MVC 2.0 + Unity 2.0(IoC) + EF4.0 实例:RoRoWoBlog 开源项目框架代码
- 开源 Asp.net mvc 用户中心开发计划
- asp.net mvc 1.0 开源
- 看一下基于ASP.NET MVC的开源社区项目Orchard
- asp.net mvc相关开源项目
- vici 开源asp.net mvc支持asp.net2.0II6.0下部署 实例下载地址
- ASP.NET MVC学习资料 新增几个开源项目
- ASP.NET MVC 2的代码以MS-PL协议开源发布
- [转]asp.net mvc相关开源项目推荐
- ASP.NET MVC 开源项目Kigg解读(1)
- (转)看了一些ASP.NET MVC开源项目后的一些想法,关于ASP.NET MVC+Repository+Service架构的一些思考
- 我要学ASP.NET MVC 3.0(十九): MVC 3.0 实例之使用开源控件实现表格排序和分页