首页 / 网页编程 / ASP.NET / MVC中ControllerActionInvoker类的InvokeActionMethodWithFilters详解
        
            MVC中ControllerActionInvoker类的InvokeActionMethodWithFilters详解2011-08-15 博客园 情三首先呢,你得先掌握Linq的扩展方法Aggregate的使用,具体可以查看我转载的一篇文章[Linq] Enumerable.Aggregate我们把Aggregate反编译出来的代码也贴一下:public static TAccumulate Aggregate<TSource, TAccumulate>(this  IEnumerable<TSource> source,
  TAccumulate seed,
  Func<TAccumulate, TSource, TAccumulate> func)
{
  // ... 省略部分代码 ...
  TAccumulate local = seed;
  foreach (TSource local2 in source)
  {
   local = func(local, local2);
  }
  return local;
}下面是InvokeActionMethodWithFilters这个方法的代码protected virtual ActionExecutedContext InvokeActionMethodWithFilters (ControllerContext controllerContext, IList<IActionFilter> filters,  ActionDescriptor actionDescriptor, IDictionary<string, object> parameters) {
       ActionExecutingContext preContext = new ActionExecutingContext (controllerContext, actionDescriptor, parameters);
       Func<ActionExecutedContext> continuation = () =>
         new ActionExecutedContext(controllerContext, actionDescriptor, false  /* canceled */, null /* exception */) {
           Result = InvokeActionMethod(controllerContext, actionDescriptor,  parameters)
         };
       // need to reverse the filter list because the continuations are  built up backward
       Func<ActionExecutedContext> thunk = filters.Reverse().Aggregate (continuation,
         (next, filter) => () => InvokeActionMethodFilter(filter,  preContext, next));
       /*-----------------这里是我的注释----------------
        * 我们要注意的是这里Aggregate返回的是一个Func委托,它并不执行委托,即每次都 返回() => InvokeActionMethodFilter(filter, preContext, next),只不过每次的filter,next 不一样而已.
        * Linq扩展方法Aggregate在foreach循环IEnumerable<TSource>之前,已经对 next做了赋值工作,即:next=continuation;
        * foreach第一个元素完之后:next其实是等同于: 
        * () => InvokeActionMethodFilter(
        *                filter,     //filter参数不分析了,即是 IEnumerable<TSource>第一,二,三...个元素
        *                preContext,
        *                continuation
        *                ),       //我们暂且叫它做next1吧 
        *如果还要再具体点就是:
        *() => InvokeActionMethodFilter(
        *                filter,
        *                preContext,
        *                () =>new ActionExecutedContext (controllerContext, actionDescriptor, false , null ) { Result = InvokeActionMethod (controllerContext, actionDescriptor, parameters) };
        *                ), //即把continuation,替换为实际的代码 
        * 第二次foreach完之后:next其实是等同于:   
        * () => InvokeActionMethodFilter(
        *                filter,
        *                preContext,
        *                next1
        *                ),我们暂且叫它做next2吧
        * 再具体点,就是
        * () => InvokeActionMethodFilter(
        *                filter,
        *                preContext,
        *                () => InvokeActionMethodFilter (filter, preContext, continuation)
        *                ),即把next1替换为实际代码
        * 如果还要再具体点就是:
        * () => InvokeActionMethodFilter(
        *                filter,
        *                preContext,
        *                () => InvokeActionMethodFilter (filter, preContext, () =>new ActionExecutedContext(controllerContext,  actionDescriptor, false , null ) { Result = InvokeActionMethod(controllerContext,  actionDescriptor, parameters) };)
        *                )//即把continuation,替换为实际的代码
        *                //假设我们叫他做next2吧
        *
        * 其它的依此类推
        * 我们假设只有两个元素,所以foreach只循环了两次,就返回了,所以Aggregate扩展 方法执行完后返回的其实就是next2
        *
        * */
       return thunk();
       /*接上面返回来的委托.开始执行委托.
        * 首先,它调用外围的匿名函数,去调用InvokeActionMethodFilter函数
        * 在InvokeActionMethodFilter函数里面.做了判断.如果我们的filter拦截器做了实 质性的拦截动作,它直接返回
        *       filter.OnActionExecuting(preContext);
        *         if (preContext.Result != null) {
        *           return new ActionExecutedContext(preContext,  preContext.ActionDescriptor, true , null ) {
        *           Result = preContext.Result
        *         };
        *        }
        * 否则的话.它开始调用内围的匿名函数,去调用InvokeActionMethodFilter函数
        * 流程的话.则是跟第一步一样的
        * 然后以此类推...
        * 最终,流程完成
        *
        * 也就是说,我们的程序没有通过哪个filter的验证,那么它后面的filter就不用去验 证了,因为它比较低级的验证都没通过.更别谈高级验证了,就像找工作面试一样,,HR面试都没通过..更甭 谈老板面试了
        *
        * */
     }