1
- using LogicBuilder . Expressions . Utils ;
1
+ using AutoMapper . Extensions . ExpressionMapping ;
2
+ using AutoMapper . Internal ;
3
+ using LogicBuilder . Expressions . Utils ;
2
4
using Microsoft . AspNetCore . OData . Query ;
3
5
using System ;
6
+ using System . Collections . Generic ;
7
+ using System . Linq ;
4
8
using System . Linq . Expressions ;
5
9
6
10
namespace AutoMapper . AspNet . OData . Visitors
7
11
{
8
12
internal class FilterAppender : ExpressionVisitor
9
13
{
10
- public FilterAppender ( Expression expression , ODataExpansionOptions expansion , ODataQueryContext context )
14
+ public FilterAppender ( Expression expression , ODataExpansionOptions expansion , ODataQueryContext context , IMapper mapper )
11
15
{
12
16
this . expansion = expansion ;
13
17
this . expression = expression ;
14
18
this . context = context ;
19
+ this . mapper = mapper ;
15
20
}
16
21
17
22
private readonly ODataExpansionOptions expansion ;
18
23
private readonly Expression expression ;
19
24
private readonly ODataQueryContext context ;
25
+ private readonly IMapper mapper ;
20
26
21
- public static Expression AppendFilter ( Expression expression , ODataExpansionOptions expansion , ODataQueryContext context )
22
- => new FilterAppender ( expression , expansion , context ) . Visit ( expression ) ;
27
+ public static Expression AppendFilter ( Expression expression , ODataExpansionOptions expansion , ODataQueryContext context , IMapper mapper )
28
+ => new FilterAppender ( expression , expansion , context , mapper ) . Visit ( expression ) ;
23
29
24
30
protected override Expression VisitMethodCall ( MethodCallExpression node )
25
31
{
@@ -28,14 +34,70 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
28
34
&& elementType == node . Type . GetUnderlyingElementType ( )
29
35
&& this . expression . ToString ( ) . StartsWith ( node . ToString ( ) ) ) //makes sure we're not updating some nested "Select"
30
36
{
37
+ Type parentUnderlyingType = node . Arguments [ 0 ] . Type . GetUnderlyingElementType ( ) ;
38
+ Type nodeUnderlyingType = elementType ;
39
+ LambdaExpression filter = GetFilterExpression ( ) ;
40
+ var replacedParent = GetNewParentExpression ( ) ;
41
+ var listOfArgumentsForNewMethod = GetArgumentsForNewMethod ( ) ;
42
+
31
43
return Expression . Call
32
44
(
33
45
node . Method . DeclaringType ,
34
- "Where" ,
35
- new Type [ ] { node . GetUnderlyingElementType ( ) } ,
36
- node ,
37
- expansion . FilterOptions . FilterClause . GetFilterExpression ( elementType , context )
46
+ node . Method . Name ,
47
+ node . Method . GetGenericArguments ( ) ,
48
+ listOfArgumentsForNewMethod
38
49
) ;
50
+
51
+ LambdaExpression GetFilterExpression ( )
52
+ {
53
+ LambdaExpression filterExpression = expansion . FilterOptions . FilterClause . GetFilterExpression ( elementType , context ) ;
54
+
55
+ if ( parentUnderlyingType != nodeUnderlyingType )
56
+ {
57
+ var typeMap = mapper . ConfigurationProvider . Internal ( ) . ResolveTypeMap ( sourceType : parentUnderlyingType , destinationType : nodeUnderlyingType ) ;
58
+ if ( typeMap != null )
59
+ {
60
+ Type sourceType = typeof ( Func < , > ) . MakeGenericType ( nodeUnderlyingType , typeof ( bool ) ) ;
61
+ Type destType = typeof ( Func < , > ) . MakeGenericType ( parentUnderlyingType , typeof ( bool ) ) ;
62
+ Type sourceExpressionype = typeof ( Expression < > ) . MakeGenericType ( sourceType ) ;
63
+ Type destExpressionType = typeof ( Expression < > ) . MakeGenericType ( destType ) ;
64
+ filterExpression = mapper . MapExpression ( filterExpression , sourceExpressionype , destExpressionType ) ;
65
+ }
66
+ }
67
+
68
+ return filterExpression ;
69
+ }
70
+
71
+ Expression GetNewParentExpression ( )
72
+ {
73
+ return new ReplaceExpressionVisitor
74
+ (
75
+ node . Arguments [ 0 ] ,
76
+ Expression . Call
77
+ (
78
+ node . Method . DeclaringType ,
79
+ "Where" ,
80
+ [ parentUnderlyingType ] ,
81
+ node . Arguments [ 0 ] ,
82
+ filter
83
+ )
84
+ ) . Visit ( node . Arguments [ 0 ] ) ;
85
+ }
86
+
87
+ Expression [ ] GetArgumentsForNewMethod ( )
88
+ {
89
+ return
90
+ [
91
+ .. node . Arguments . Aggregate ( new List < Expression > ( ) , ( lst , next ) =>
92
+ {
93
+ if ( next == node . Arguments [ 0 ] )
94
+ lst . Add ( replacedParent ) ;
95
+ else
96
+ lst . Add ( next ) ;
97
+ return lst ;
98
+ } )
99
+ ] ;
100
+ }
39
101
}
40
102
41
103
return base . VisitMethodCall ( node ) ;
0 commit comments