程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> MVC中ControllerActionInvoker類的InvokeActionMethodWithFilters詳解

MVC中ControllerActionInvoker類的InvokeActionMethodWithFilters詳解

編輯:關於ASP.NET

首先呢,你得先掌握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面試都沒通過..更甭 談老板面試了
        *
        * */
     }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved