@@ -77,40 +77,103 @@ public static BotControllerHandlers MakeHandlers()
7777 . OrderBy ( c => c . on . Filter == null )
7878 . ThenByDescending ( c => c . on . Order )
7979
80- . Select ( c => new HandlerItem ( c . on . Handler , c . m , GetFilter ( c . m , c . on . Filter ) ) ) ;
80+ . Select ( c => new HandlerItem ( c . on . Handler , c . m , GetFilter ( c . m , c . on ) ) ) ;
8181
8282 return new BotControllerHandlers ( handlers ) ;
8383
84- static ActionFilter ? GetFilter ( MethodInfo target , string ? filterMethod )
84+ static ActionFilter ? GetFilter ( MethodInfo target , OnAttribute on )
8585 {
86- if ( filterMethod == null )
86+ var filters = target . GetCustomAttributes < FilterAttribute > ( ) . ToArray ( ) ;
87+
88+ if ( filters . Length == 0 && on . Filter == null )
8789 {
8890 return null ;
8991 }
9092
91- if ( filterMethod . Contains ( '.' ) )
93+ if ( filters . Length != 0 && on . Filter != null )
9294 {
93- var typeName = filterMethod . Substring ( 0 , filterMethod . LastIndexOf ( '.' ) ) ;
94- var methodName = filterMethod . Substring ( filterMethod . LastIndexOf ( '.' ) + 1 ) ;
95+ throw new BotfException ( "Use only Filter() attribute to pass filter methods of handlers" ) ;
96+ }
9597
96- var type = Type . GetType ( typeName ) ;
97- if ( type == null )
98- {
99- throw new BotfException ( $ "Filter method name is wrong. Can't find class type `{ typeName } `. Action method is `{ target . DeclaringType ! . Name } .{ target . Name } `") ;
100- }
98+ if ( on . Filter != null )
99+ {
100+ var methodInTarget = FilterAttribute . GetMethod ( on . Filter , target . DeclaringType ) ;
101+ CheckFilterMethod ( methodInTarget , on . Filter , target . DeclaringType ! . Name ) ;
102+ return ( ActionFilter ) ActionFilter . CreateDelegate ( typeof ( ActionFilter ) , methodInTarget ! ) ;
103+ }
104+
105+ if ( filters . Length == 0 )
106+ {
107+ return null ;
108+ }
101109
102- var method = type . GetMethod ( methodName , BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic ) ;
103- CheckFilterMethod ( method , methodName , typeName , target ) ;
110+ ActionFilter ? result = null ;
111+
112+ for ( int i = 0 ; i < filters . Length ; i ++ )
113+ {
114+ var filter = filters [ i ] ;
115+ var method = filter . GetMethod ( target . DeclaringType ) ;
116+ CheckFilterMethod ( method , filter . Filter , target . DeclaringType ! . Name ) ;
117+ var action = ( ActionFilter ) ActionFilter . CreateDelegate ( typeof ( ActionFilter ) , method ! ) ;
104118
105- return ( ActionFilter ) ActionFilter . CreateDelegate ( typeof ( ActionFilter ) , method ! ) ;
119+ if ( result == null )
120+ {
121+ if ( filter . Operation == FilterAttribute . BoolOp . Not )
122+ {
123+ result = ( IUpdateContext ctx ) =>
124+ {
125+ ctx . SetFilterParameter ( filter . Param ) ;
126+ return ! action ( ctx ) ;
127+ } ;
128+ }
129+ else
130+ {
131+ result = ( IUpdateContext ctx ) =>
132+ {
133+ ctx . SetFilterParameter ( filter . Param ) ;
134+ return action ( ctx ) ;
135+ } ;
136+ }
137+ }
138+ else
139+ {
140+ var currentResult = result ;
141+ result = ( IUpdateContext ctx ) =>
142+ {
143+ var leftResult = currentResult ( ctx ) ;
144+
145+ ctx . SetFilterParameter ( filter . Param ) ;
146+ var rightResult = action ( ctx ) ;
147+
148+ if ( filter . Operation == FilterAttribute . BoolOp . And )
149+ {
150+ return leftResult && rightResult ;
151+ }
152+ else if ( filter . Operation == FilterAttribute . BoolOp . Or )
153+ {
154+ return leftResult || rightResult ;
155+ }
156+ else if ( filter . Operation == FilterAttribute . BoolOp . AndNot )
157+ {
158+ return leftResult && ! rightResult ;
159+ }
160+ else if ( filter . Operation == FilterAttribute . BoolOp . OrNot )
161+ {
162+ return leftResult || ! rightResult ;
163+ }
164+ else if ( filter . Operation == FilterAttribute . BoolOp . Not )
165+ {
166+ throw new NotSupportedException ( $ "Operation NOT is supported only for first filter") ;
167+ }
168+
169+ throw new NotSupportedException ( $ "Operation type { filter . Operation } is not supported") ;
170+ } ;
171+ }
106172 }
107-
108- var methodInTarget = target . DeclaringType ! . GetMethod ( filterMethod , BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic ) ;
109- CheckFilterMethod ( methodInTarget , filterMethod , target . DeclaringType . Name , target ) ;
110173
111- return ( ActionFilter ) ActionFilter . CreateDelegate ( typeof ( ActionFilter ) , methodInTarget ! ) ;
174+ return result ;
112175
113- static void CheckFilterMethod ( MethodInfo ? filter , string methodName , string typeName , MethodInfo target )
176+ static void CheckFilterMethod ( MethodInfo ? filter , string methodName , string typeName )
114177 {
115178 if ( filter == null
116179 || filter . ReturnType != typeof ( bool )
0 commit comments