当前位置: 移动技术网 > 科技>操作系统>windows > MVC中IActionFilter过滤器俄罗斯套娃的实现方式

MVC中IActionFilter过滤器俄罗斯套娃的实现方式

2019年08月08日  | 移动技术网科技  | 我要评论

普洱茶的产地在哪,姬野爱 护士,护士献身捐精

看mvc的源码我们知道,它是在 controlleractioninvoker 类中执行 invokeaction 方法来实现过滤器和action方法执行的。 

通过查看源码我们知道,他是通过调用 invokeactionmethodwithfilters 方法来实现iactionfilter过滤器和action方法执行的,如图 

点进去这个方法我们可以看到 

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 }

看到这里我直接懵逼了,由于它委托中嵌套了委托而且还简写,还调用了扩展方法aggregate累加器,所以很难直接看懂,这到底是怎么执行代码的呐?我来把代码整理如下 

 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     }

咋一看,还是不知所云,一步一步来,

首先,我们先要知道 aggregate 这个扩展方法是怎么执行的,直接看源码如下 

 

看了源码就很容易理解了,它就是遍历数据源来循环执行传递过来的委托,并把结果当成参数,执行下一次循环的委托。

所有我整理了一个容易理解的一串代码 

 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     }

我是用一个int数组来模拟iactionfilter集合,其它的写法都和mvc框架的写法一样。

运行结果为 如图

 

看到这里,你是否明白了,它就是通过 委托里嵌套委托 来巧妙的实现了俄罗斯套娃的形式来实现iactionfilter过滤器和action方法的执行。

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网