MVC in IActionFilter filter matryoshka implementation

Look mvc source we know, it is  ControllerActionInvoker  execution class  InvokeAction  way to implement a filter and action execution method. 

We know that by looking at the source code, he is by calling  InvokeActionMethodWithFilters  methods to achieve IActionFilter filter and action execution method, as 

Point into this way we can see 

1 protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
2 {
3     ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
4     Func<ActionExecutedContext> seed = () => new ActionExecutedContext(controllerContext, actionDescriptor, false, null)
5     {
6         Result = this.InvokeActionMethod(controllerContext, actionDescriptor, parameters)
7     };
8     return filters.Reverse<IActionFilter>().Aggregate(seed, (Func<ActionExecutedContext> next, IActionFilter filter) => () => ControllerActionInvoker.InvokeActionMethodFilter(filter, preContext, next))();
9 }
View Code

I see here a direct ignorant force, because it has nested delegate commission but also shorthand, also called extension methods Aggregate accumulator, it is difficult to directly read, which in the end is how the implementation of the code of na? I'll put the code are summarized as follows 

 1    public class Class1
 2     {
 3 
 4         protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
 5         {
 6             ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
 7 
 8             Func<ActionExecutedContext> seed = () => new ActionExecutedContext(controllerContext, actionDescriptor, false, null)
 9             {
10                 Result = this.InvokeActionMethod(controllerContext, actionDescriptor, parameters)
11             };
12 
13             Func<Func<ActionExecutedContext>, IActionFilter, Func<ActionExecutedContext>> secondParam =
14                 (Func<ActionExecutedContext> next, IActionFilter filter) =>
15                 {
16                     Func<ActionExecutedContext> returnFunc = () =>
17                     {
18                         return Class1.InvokeActionMethodFilter(filter, preContext, next);
19                     };
20 
21                     return returnFunc;
22 
23                     //这个是简写
24                     //return () => Class1.InvokeActionMethodFilter(filter, preContext, next);                    
25                 };
26 
27             return filters.Reverse<IActionFilter>().Aggregate(seed,
28                 //(Func<ActionExecutedContext> next, IActionFilter filter) => () => Class1.InvokeActionMethodFilter(filter, preContext, next)
29                 secondParam
30                 )
31                 .Invoke();
32         }
33 
34         internal static ActionExecutedContext InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func<ActionExecutedContext> continuation)
35         {
36             filter.OnActionExecuting(preContext);
37             if (preContext.Result != null)
38             {
39                 return new ActionExecutedContext(preContext, preContext.ActionDescriptor, true, null)
40                 {
41                     Result = preContext.Result
42                 };
43             }
44             bool flag = false;
45             ActionExecutedContext actionExecutedContext = null;
46             try
47             {
48                 actionExecutedContext = continuation();
49             }
50             catch (ThreadAbortException)
51             {
52                 actionExecutedContext = new ActionExecutedContext(preContext, preContext.ActionDescriptor, false, null);
53                 filter.OnActionExecuted(actionExecutedContext);
54                 throw;
55             }
56             catch (Exception exception)
57             {
58                 flag = true;
59                 actionExecutedContext = new ActionExecutedContext(preContext, preContext.ActionDescriptor, false, exception);
60                 filter.OnActionExecuted(actionExecutedContext);
61                 if (!actionExecutedContext.ExceptionHandled)
62                 {
63                     throw;
64                 }
65             }
66             if (!flag)
67             {
68                 filter.OnActionExecuted(actionExecutedContext);
69             }
70             return actionExecutedContext;
71         }
72 
73         protected virtual ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
74         {
75             object actionReturnValue = actionDescriptor.Execute(controllerContext, parameters);
76             return this.CreateActionResult(controllerContext, actionDescriptor, actionReturnValue);
77         }
78 
79         protected virtual ActionResult CreateActionResult(ControllerContext controllerContext, ActionDescriptor actionDescriptor, object actionReturnValue)
80         {
81             if (actionReturnValue == null)
82             {
83                 return new EmptyResult();
84             }
85             ActionResult arg_29_0;
86             if ((arg_29_0 = (actionReturnValue as ActionResult)) == null)
87             {
88                 arg_29_0 = new ContentResult();
89                 //(arg_29_0 = new ContentResult()).Content = Convert.ToString(actionReturnValue, CultureInfo.InvariantCulture);
90                 (arg_29_0 as ContentResult).Content = Convert.ToString(actionReturnValue, CultureInfo.InvariantCulture);
91             }
92             return arg_29_0;
93         }
94 
95     }
View Code

At first sight, or unintelligible, step by step,

First of all, we need to know Aggregate This extension method is how to perform a direct look at the source code as follows 

 

Read the source code is easy to understand, it is the loop through the data source to entrust execution to pass over, and the results as a parameter, the next time through the loop of the commission.

All I have put together a string of codes easy to understand 

 1     public class Class2
 2     {
 3 
 4         public void Test()
 5         {
 6             var preContext = new ActionExecutingContext();
 7 
 8             Func<ActionExecutedContext> seed = () =>
 9             {
10                 Console.WriteLine("执行action");
11                 return new ActionExecutedContext();
12             };
13 
14             int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
15 
16             Func<Func<ActionExecutedContext>, int, Func<ActionExecutedContext>> secondParam =
17             (Func<ActionExecutedContext> next, int filter) =>
18             {
19                 return () => this.getStr(next, filter, preContext);
20             };
21 
22             var reFunc2 = arr.Reverse().Aggregate<int, Func<ActionExecutedContext>>(seed, secondParam);
23             reFunc2.Invoke();
24 
25         }
26 
27         public ActionExecutedContext getStr(Func<ActionExecutedContext> func, int filter, ActionExecutingContext preContext)
28         {
29 
30             Console.WriteLine("before action----" + filter + "----" + preContext.ToString());
31 
32             var res = func.Invoke();
33 
34             Console.WriteLine("before action----" + filter + "----" + res.ToString());
35 
36             return res;
37         }
38 
39     }
View Code

I was using an int array to simulate IActionFilter collection, others are writing and writing mvc framework of the same.

Operating results as shown

 

See here, you understand, it is entrusted to achieve a subtle form of matryoshka to achieve the implementation of IActionFilter filters and commissioned by the Action method in nesting.

 

Guess you like

Origin www.cnblogs.com/xiaoZhang521/p/11269677.html