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