4
4
// Created by: Alexis Kochetov
5
5
// Created: 2009.02.25
6
6
7
- using System ;
8
- using System . Collections . Generic ;
9
- using System . Linq ;
10
7
using System . Linq . Expressions ;
11
8
using Xtensive . Reflection ;
12
9
13
- namespace Xtensive . Linq
14
- {
15
- /// <summary>
16
- /// Abstract base visitor that handles methods of <see cref="IQueryable"/> and <see cref="IEnumerable{T}"/> by calling <see cref="VisitQueryableMethod"/>.
17
- /// </summary>
18
- [ Serializable ]
19
- public abstract class QueryableVisitor : ExpressionVisitor
20
- {
21
- /// <inheritdoc/>
22
- protected override Expression VisitMethodCall ( MethodCallExpression mc )
23
- {
24
- if ( mc . Arguments . Count > 0 && mc . Arguments [ 0 ] . Type == WellKnownTypes . String ) {
25
- return base . VisitMethodCall ( mc ) ;
26
- }
27
-
28
- var method = GetQueryableMethod ( mc ) ;
29
- if ( method == null ) {
30
- return base . VisitMethodCall ( mc ) ;
31
- }
32
-
33
- return VisitQueryableMethod ( mc , method . Value ) ;
34
- }
35
-
36
- /// <summary>
37
- /// Visits method of <see cref="IQueryable"/> or <see cref="IEnumerable{T}"/>.
38
- /// </summary>
39
- /// <param name="mc">The method call expression.</param>
40
- /// <param name="methodKind">Kind of the method.</param>
41
- protected abstract Expression VisitQueryableMethod ( MethodCallExpression mc , QueryableMethodKind methodKind ) ;
10
+ namespace Xtensive . Linq ;
42
11
43
- /// <summary>
44
- /// Parses <see cref="QueryableMethodKind"/> for the specified expression.
45
- /// </summary>
46
- /// <param name="call">A call to process.</param>
47
- /// <returns><see cref="QueryableMethodKind"/> for the specified expression,
48
- /// or null if method is not a LINQ method.</returns>
49
- public static QueryableMethodKind ? GetQueryableMethod ( MethodCallExpression call )
50
- {
51
- if ( call == null ) {
52
- return null ;
53
- }
54
-
55
- var declaringType = call . Method . DeclaringType ;
56
- if ( declaringType == WellKnownTypes . Queryable || declaringType == WellKnownTypes . Enumerable ) {
57
- return ParseQueryableMethodKind ( call . Method . Name ) ;
58
- }
12
+ /// <summary>
13
+ /// Abstract base visitor that handles methods of <see cref="IQueryable"/> and <see cref="IEnumerable{T}"/> by calling <see cref="VisitQueryableMethod"/>.
14
+ /// </summary>
15
+ [ Serializable ]
16
+ public abstract class QueryableVisitor : ExpressionVisitor
17
+ {
18
+ private static readonly Dictionary < string , QueryableMethodKind > QueryableMethodKindFromName = new ( ) {
19
+ [ nameof ( Queryable . Aggregate ) ] = QueryableMethodKind . Aggregate ,
20
+ [ nameof ( Queryable . All ) ] = QueryableMethodKind . All ,
21
+ [ nameof ( Queryable . Any ) ] = QueryableMethodKind . Any ,
22
+ [ "AsEnumerable" ] = QueryableMethodKind . AsEnumerable ,
23
+ [ "AsQueryable" ] = QueryableMethodKind . AsQueryable ,
24
+ [ nameof ( Queryable . Average ) ] = QueryableMethodKind . Average ,
25
+ [ nameof ( Queryable . Cast ) ] = QueryableMethodKind . Cast ,
26
+ [ nameof ( Queryable . Concat ) ] = QueryableMethodKind . Concat ,
27
+ [ nameof ( Queryable . Contains ) ] = QueryableMethodKind . Contains ,
28
+ [ nameof ( Queryable . Count ) ] = QueryableMethodKind . Count ,
29
+ [ nameof ( Queryable . DefaultIfEmpty ) ] = QueryableMethodKind . DefaultIfEmpty ,
30
+ [ nameof ( Queryable . Distinct ) ] = QueryableMethodKind . Distinct ,
31
+ [ nameof ( Queryable . DistinctBy ) ] = QueryableMethodKind . DistinctBy ,
32
+ [ nameof ( Queryable . ElementAt ) ] = QueryableMethodKind . ElementAt ,
33
+ [ nameof ( Queryable . ElementAtOrDefault ) ] = QueryableMethodKind . ElementAtOrDefault ,
34
+ [ nameof ( Queryable . Except ) ] = QueryableMethodKind . Except ,
35
+ [ nameof ( Queryable . First ) ] = QueryableMethodKind . First ,
36
+ [ nameof ( Queryable . FirstOrDefault ) ] = QueryableMethodKind . FirstOrDefault ,
37
+ [ nameof ( Queryable . GroupBy ) ] = QueryableMethodKind . GroupBy ,
38
+ [ nameof ( Queryable . GroupJoin ) ] = QueryableMethodKind . GroupJoin ,
39
+ [ nameof ( Queryable . Intersect ) ] = QueryableMethodKind . Intersect ,
40
+ [ nameof ( Queryable . Join ) ] = QueryableMethodKind . Join ,
41
+ [ nameof ( Queryable . Last ) ] = QueryableMethodKind . Last ,
42
+ [ nameof ( Queryable . LastOrDefault ) ] = QueryableMethodKind . LastOrDefault ,
43
+ [ nameof ( Queryable . LongCount ) ] = QueryableMethodKind . LongCount ,
44
+ [ nameof ( Queryable . Max ) ] = QueryableMethodKind . Max ,
45
+ [ nameof ( Queryable . Min ) ] = QueryableMethodKind . Min ,
46
+ [ nameof ( Queryable . OfType ) ] = QueryableMethodKind . OfType ,
47
+ [ nameof ( Queryable . OrderBy ) ] = QueryableMethodKind . OrderBy ,
48
+ [ nameof ( Queryable . OrderByDescending ) ] = QueryableMethodKind . OrderByDescending ,
49
+ [ nameof ( Queryable . Reverse ) ] = QueryableMethodKind . Reverse ,
50
+ [ nameof ( Queryable . Select ) ] = QueryableMethodKind . Select ,
51
+ [ nameof ( Queryable . SelectMany ) ] = QueryableMethodKind . SelectMany ,
52
+ [ nameof ( Queryable . SequenceEqual ) ] = QueryableMethodKind . SequenceEqual ,
53
+ [ nameof ( Queryable . Single ) ] = QueryableMethodKind . Single ,
54
+ [ nameof ( Queryable . SingleOrDefault ) ] = QueryableMethodKind . SingleOrDefault ,
55
+ [ nameof ( Queryable . Skip ) ] = QueryableMethodKind . Skip ,
56
+ [ nameof ( Queryable . SkipWhile ) ] = QueryableMethodKind . SkipWhile ,
57
+ [ nameof ( Queryable . Sum ) ] = QueryableMethodKind . Sum ,
58
+ [ nameof ( Queryable . Take ) ] = QueryableMethodKind . Take ,
59
+ [ nameof ( Queryable . TakeWhile ) ] = QueryableMethodKind . TakeWhile ,
60
+ [ nameof ( Queryable . ThenBy ) ] = QueryableMethodKind . ThenBy ,
61
+ [ nameof ( Queryable . ThenByDescending ) ] = QueryableMethodKind . ThenByDescending ,
62
+ [ "ToArray" ] = QueryableMethodKind . ToArray ,
63
+ [ "ToList" ] = QueryableMethodKind . ToList ,
64
+ [ nameof ( Queryable . Union ) ] = QueryableMethodKind . Union ,
65
+ [ nameof ( Queryable . Where ) ] = QueryableMethodKind . Where
66
+ } ;
59
67
60
- return null ;
61
- }
68
+ /// <inheritdoc/>
69
+ protected override Expression VisitMethodCall ( MethodCallExpression mc ) =>
70
+ mc . Arguments is var mcArguments
71
+ && ( mcArguments . Count > 0 && mcArguments [ 0 ] . Type == WellKnownTypes . String )
72
+ || ! ( GetQueryableMethod ( mc ) is { } method )
73
+ ? base . VisitMethodCall ( mc )
74
+ : VisitQueryableMethod ( mc , method ) ;
62
75
63
- private static QueryableMethodKind ? ParseQueryableMethodKind ( string methodName )
64
- {
65
- if ( Enum . TryParse ( methodName , out QueryableMethodKind result ) ) {
66
- return result ;
67
- }
76
+ /// <summary>
77
+ /// Visits method of <see cref="IQueryable"/> or <see cref="IEnumerable{T}"/>.
78
+ /// </summary>
79
+ /// <param name="mc">The method call expression.</param>
80
+ /// <param name="methodKind">Kind of the method.</param>
81
+ protected abstract Expression VisitQueryableMethod ( MethodCallExpression mc , QueryableMethodKind methodKind ) ;
68
82
69
- return null ;
70
- }
71
- }
72
- }
83
+ /// <summary>
84
+ /// Parses <see cref="QueryableMethodKind"/> for the specified expression.
85
+ /// </summary>
86
+ /// <param name="call">A call to process.</param>
87
+ /// <returns><see cref="QueryableMethodKind"/> for the specified expression,
88
+ /// or null if method is not a LINQ method.</returns>
89
+ public static QueryableMethodKind ? GetQueryableMethod ( MethodCallExpression call ) =>
90
+ call ? . Method . DeclaringType is { } declaringType
91
+ && ( declaringType == WellKnownTypes . Queryable || declaringType == WellKnownTypes . Enumerable )
92
+ && QueryableMethodKindFromName . TryGetValue ( call . Method . Name , out var v )
93
+ ? v
94
+ : null ;
95
+ }
0 commit comments