44using System . Linq ;
55using System . Linq . Expressions ;
66
7- namespace MockQueryable . Core
7+ namespace MockQueryable . Core ;
8+
9+ public abstract class TestQueryProvider < T , TExpressionVisitor > : IOrderedQueryable < T > , IQueryProvider
10+ where TExpressionVisitor : ExpressionVisitor , new ( )
811{
9- public abstract class TestQueryProvider < T > : IOrderedQueryable < T > , IQueryProvider
10- {
11- private IEnumerable < T > _enumerable ;
12+ private IEnumerable < T > _enumerable ;
13+
1214
1315 protected TestQueryProvider ( Expression expression )
14- {
15- Expression = expression ;
16- }
16+ {
17+ Expression = expression ;
18+ }
1719
1820 protected TestQueryProvider ( IEnumerable < T > enumerable )
19- {
20- _enumerable = enumerable ;
21- Expression = enumerable . AsQueryable ( ) . Expression ;
22- }
23-
24- public IQueryable CreateQuery ( Expression expression )
25- {
26- if ( expression is MethodCallExpression m )
27- {
28- var resultType = m . Method . ReturnType ; // it should be IQueryable<T>
29- var tElement = resultType . GetGenericArguments ( ) . First ( ) ;
30- return ( IQueryable ) CreateInstance ( tElement , expression ) ;
31- }
32-
33- return CreateQuery < T > ( expression ) ;
34- }
35-
36- public IQueryable < TEntity > CreateQuery < TEntity > ( Expression expression )
37- {
38- return ( IQueryable < TEntity > ) CreateInstance ( typeof ( TEntity ) , expression ) ;
21+ {
22+ _enumerable = enumerable ;
23+ Expression = enumerable . AsQueryable ( ) . Expression ;
24+
25+ }
26+
27+ public IQueryable CreateQuery ( Expression expression )
28+ {
29+ if ( expression is MethodCallExpression m )
30+ {
31+ var resultType = m . Method . ReturnType ; // it should be IQueryable<T>
32+ var tElement = resultType . GetGenericArguments ( ) . First ( ) ;
33+ return ( IQueryable ) CreateInstance ( tElement , expression ) ;
34+ }
35+
36+ return CreateQuery < T > ( expression ) ;
37+ }
38+
39+ public IQueryable < TEntity > CreateQuery < TEntity > ( Expression expression )
40+ {
41+ return ( IQueryable < TEntity > ) CreateInstance ( typeof ( TEntity ) , expression ) ;
3942 }
4043
41- private object CreateInstance ( Type tElement , Expression expression )
44+ protected abstract object CreateInstance ( Type tElement , Expression expression ) ;
45+
46+
47+ public object Execute ( Expression expression )
4248 {
43- var queryType = GetType ( ) . GetGenericTypeDefinition ( ) . MakeGenericType ( tElement ) ;
44- return Activator . CreateInstance ( queryType , expression ) ;
45- }
46-
47- public object Execute ( Expression expression )
48- {
49- return CompileExpressionItem < object > ( expression ) ;
50- }
51-
52- public TResult Execute < TResult > ( Expression expression )
53- {
54- return CompileExpressionItem < TResult > ( expression ) ;
55- }
56-
57- IEnumerator < T > IEnumerable < T > . GetEnumerator ( )
58- {
59- if ( _enumerable == null ) _enumerable = CompileExpressionItem < IEnumerable < T > > ( Expression ) ;
60- return _enumerable . GetEnumerator ( ) ;
61- }
62-
63- IEnumerator IEnumerable . GetEnumerator ( )
64- {
65- if ( _enumerable == null ) _enumerable = CompileExpressionItem < IEnumerable < T > > ( Expression ) ;
66- return _enumerable . GetEnumerator ( ) ;
67- }
68-
69- public Type ElementType => typeof ( T ) ;
70-
71- public Expression Expression { get ; }
72-
73- public IQueryProvider Provider => this ;
74-
75- private static TResult CompileExpressionItem < TResult > ( Expression expression )
76- {
77- var visitor = new TestExpressionVisitor ( ) ;
78- var body = visitor . Visit ( expression ) ;
79- var f = Expression . Lambda < Func < TResult > > ( body ?? throw new InvalidOperationException ( $ "{ nameof ( body ) } is null") , ( IEnumerable < ParameterExpression > ) null ) ;
80- return f . Compile ( ) ( ) ;
81- }
82- }
49+ return CompileExpressionItem < object > ( expression ) ;
50+ }
51+
52+ public virtual TResult Execute < TResult > ( Expression expression )
53+ {
54+
55+ return CompileExpressionItem < TResult > ( expression ) ;
56+ }
57+
58+ IEnumerator < T > IEnumerable < T > . GetEnumerator ( )
59+ {
60+ _enumerable ??= CompileExpressionItem < IEnumerable < T > > ( Expression ) ;
61+ return _enumerable . GetEnumerator ( ) ;
62+ }
63+
64+ IEnumerator IEnumerable . GetEnumerator ( )
65+ {
66+ _enumerable ??= CompileExpressionItem < IEnumerable < T > > ( Expression ) ;
67+ return _enumerable . GetEnumerator ( ) ;
68+ }
69+
70+ public Type ElementType => typeof ( T ) ;
71+
72+ public Expression Expression { get ; }
73+
74+ public IQueryProvider Provider => this ;
75+
76+ private static TResult CompileExpressionItem < TResult > ( Expression expression )
77+ {
78+ var visitor = new TExpressionVisitor ( ) ;
79+ var body = visitor . Visit ( expression ) ;
80+ var f = Expression . Lambda < Func < TResult > > (
81+ body ?? throw new InvalidOperationException ( $ "{ nameof ( body ) } is null") ,
82+ ( IEnumerable < ParameterExpression > ) null ) ;
83+ return f . Compile ( ) ( ) ;
84+ }
8385}
0 commit comments