4
4
using CouchDB . Driver . Types ;
5
5
using Flurl . Http ;
6
6
using System ;
7
+ using System . Collections . Generic ;
7
8
using System . Linq ;
8
9
using System . Linq . Expressions ;
9
10
using System . Reflection ;
@@ -32,21 +33,40 @@ public override string GetQueryText(Expression expression)
32
33
33
34
public override object Execute ( Expression e , bool completeResponse )
34
35
{
36
+ MethodInfo _filterMethodInfo = null ;
37
+ Expression [ ] _filteringExpressions = Array . Empty < Expression > ( ) ;
38
+ if ( e is MethodCallExpression m )
39
+ {
40
+ if (
41
+ m . Method . Name == "First" ||
42
+ m . Method . Name == "FirstOrDefault" ||
43
+ m . Method . Name == "Last" ||
44
+ m . Method . Name == "LastOrDefault" ||
45
+ m . Method . Name == "Single" ||
46
+ m . Method . Name == "SingleOrDefault" )
47
+ {
48
+ _filterMethodInfo = m . Method ;
49
+ _filteringExpressions = m . Arguments . Skip ( 1 ) . ToArray ( ) ;
50
+ e = m . Arguments [ 0 ] ;
51
+ }
52
+ }
53
+
35
54
var body = Translate ( e ) ;
36
55
Type elementType = TypeSystem . GetElementType ( e . Type ) ;
37
56
38
- MethodInfo method = typeof ( CouchQueryProvider ) . GetMethod ( "GetCouchList" ) ;
57
+ MethodInfo method = typeof ( CouchQueryProvider ) . GetMethod ( nameof ( CouchQueryProvider . GetCouchListOrFiltered ) ) ;
39
58
MethodInfo generic = method . MakeGenericMethod ( elementType ) ;
40
- return generic . Invoke ( this , new [ ] { body } ) ;
59
+ var result = generic . Invoke ( this , new [ ] { body , ( object ) _filterMethodInfo , _filteringExpressions } ) ;
60
+ return result ;
41
61
}
42
-
62
+
43
63
private string Translate ( Expression expression )
44
64
{
45
65
expression = Evaluator . PartialEval ( expression ) ;
46
66
return new QueryTranslator ( _settings ) . Translate ( expression ) ;
47
67
}
48
68
49
- public CouchList < T > GetCouchList < T > ( string body )
69
+ public object GetCouchListOrFiltered < T > ( string body , MethodInfo filteringMethodInfo , Expression [ ] filteringExpressions )
50
70
{
51
71
FindResult < T > result = _flurlClient
52
72
. Request ( _connectionString )
@@ -56,7 +76,49 @@ public CouchList<T> GetCouchList<T>(string body)
56
76
. SendRequest ( ) ;
57
77
58
78
var couchList = new CouchList < T > ( result . Docs . ToList ( ) , result . Bookmark , result . ExecutionStats ) ;
59
- return couchList ;
79
+
80
+ if ( filteringMethodInfo == null )
81
+ {
82
+ return couchList ;
83
+ }
84
+
85
+ var filteringMethods = typeof ( Enumerable ) . GetMethods ( )
86
+ . Where ( m =>
87
+ m . Name == filteringMethodInfo . Name &&
88
+ m . GetParameters ( ) . Length - 1 == filteringExpressions . Length )
89
+ . OrderBy ( m => m . GetParameters ( ) . Length ) . ToList ( ) ;
90
+
91
+
92
+ var invokeParameter = new object [ filteringExpressions . Length + 1 ] ;
93
+ invokeParameter [ 0 ] = couchList ;
94
+
95
+ bool IsRightOverload ( MethodInfo m )
96
+ {
97
+ ParameterInfo [ ] parameters = m . GetParameters ( ) ;
98
+ for ( var i = 0 ; i < filteringExpressions . Length ; i ++ )
99
+ {
100
+ var lamdaExpression = filteringExpressions [ i ] as UnaryExpression ;
101
+ if ( lamdaExpression == null )
102
+ {
103
+ return false ;
104
+ }
105
+
106
+ if ( lamdaExpression . Operand . Type != parameters [ i + 1 ] . ParameterType )
107
+ {
108
+ return false ;
109
+ }
110
+ invokeParameter [ i + 1 ] = lamdaExpression . Operand ;
111
+ }
112
+ return true ;
113
+ }
114
+
115
+ MethodInfo rightOverload = filteringMethods . Single ( IsRightOverload ) ;
116
+
117
+ MethodInfo enumerableGenericFilteringMethod = rightOverload . MakeGenericMethod ( typeof ( T ) ) ;
118
+
119
+
120
+ var filtered = enumerableGenericFilteringMethod . Invoke ( null , invokeParameter ) ;
121
+ return filtered ;
60
122
}
61
123
}
62
124
}
0 commit comments