21
21
using System . Threading ;
22
22
using System . Reflection ;
23
23
24
+ // for a good blog post on implementing LINQ query providers see Matt Warren's blog posts
25
+ // see: http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx
26
+
24
27
namespace MongoDB . Driver . Linq
25
28
{
26
29
/// <summary>
27
30
/// An implementation of IQueryProvider for querying a MongoDB collection.
28
31
/// </summary>
29
32
public class MongoQueryProvider : IQueryProvider
30
33
{
31
- // private static fields
32
- private static Dictionary < Type , Func < MongoQueryProvider , Expression , IQueryable > > __createQueryDelegates = new Dictionary < Type , Func < MongoQueryProvider , Expression , IQueryable > > ( ) ;
33
- private static MethodInfo __createQueryGenericMethodDefinition ;
34
- private static Dictionary < Type , Func < MongoQueryProvider , Expression , object > > __executeDelegates = new Dictionary < Type , Func < MongoQueryProvider , Expression , object > > ( ) ;
35
- private static MethodInfo __executeGenericMethodDefinition ;
36
- private static object __staticLock = new object ( ) ;
37
-
38
34
// private fields
39
35
private MongoCollection _collection ;
40
36
41
- // static constructor
42
- static MongoQueryProvider ( )
43
- {
44
- foreach ( var methodInfo in typeof ( MongoQueryProvider ) . GetMethods ( BindingFlags . Public | BindingFlags . Instance | BindingFlags . DeclaredOnly ) )
45
- {
46
- if ( methodInfo . Name == "CreateQuery" && methodInfo . IsGenericMethodDefinition )
47
- {
48
- __createQueryGenericMethodDefinition = methodInfo ;
49
- }
50
- if ( methodInfo . Name == "Execute" && methodInfo . IsGenericMethodDefinition )
51
- {
52
- __executeGenericMethodDefinition = methodInfo ;
53
- }
54
- }
55
- }
56
-
57
37
// constructors
58
38
/// <summary>
59
39
/// Initializes a new instance of the MongoQueryProvider class.
@@ -67,61 +47,6 @@ public MongoQueryProvider(MongoCollection collection)
67
47
_collection = collection ;
68
48
}
69
49
70
- // private static methods
71
- private static Func < MongoQueryProvider , Expression , IQueryable > GetCreateQueryDelegate ( Type type )
72
- {
73
- lock ( __staticLock )
74
- {
75
- Func < MongoQueryProvider , Expression , IQueryable > createQueryDelegate ;
76
- if ( ! __createQueryDelegates . TryGetValue ( type , out createQueryDelegate ) )
77
- {
78
- var createQueryMethodInfo = __createQueryGenericMethodDefinition . MakeGenericMethod ( type ) ;
79
-
80
- // lambdaExpression = (provider, expression) => (IQueryable) provider.CreateQuery<T>(expression)
81
- var providerParameter = Expression . Parameter ( typeof ( MongoQueryProvider ) , "provider" ) ;
82
- var expressionParameter = Expression . Parameter ( typeof ( Expression ) , "expression" ) ;
83
- var lambdaExpression = Expression . Lambda < Func < MongoQueryProvider , Expression , IQueryable > > (
84
- Expression . Convert (
85
- Expression . Call ( providerParameter , createQueryMethodInfo , expressionParameter ) ,
86
- typeof ( IQueryable )
87
- ) ,
88
- providerParameter ,
89
- expressionParameter
90
- ) ;
91
- createQueryDelegate = lambdaExpression . Compile ( ) ;
92
- __createQueryDelegates . Add ( type , createQueryDelegate ) ;
93
- }
94
- return createQueryDelegate ;
95
- }
96
- }
97
-
98
- private static Func < MongoQueryProvider , Expression , object > GetExecuteDelegate ( Type type )
99
- {
100
- lock ( __staticLock )
101
- {
102
- Func < MongoQueryProvider , Expression , object > executeDelegate ;
103
- if ( ! __executeDelegates . TryGetValue ( type , out executeDelegate ) )
104
- {
105
- var executeMethodInfo = __executeGenericMethodDefinition . MakeGenericMethod ( type ) ;
106
-
107
- // lambdaExpression = (provider, expression) => (object) provider.Execute<T>(expression)
108
- var providerParameter = Expression . Parameter ( typeof ( MongoQueryProvider ) , "provider" ) ;
109
- var expressionParameter = Expression . Parameter ( typeof ( Expression ) , "expression" ) ;
110
- var lambdaExpression = Expression . Lambda < Func < MongoQueryProvider , Expression , object > > (
111
- Expression . Convert (
112
- Expression . Call ( providerParameter , executeMethodInfo , expressionParameter ) ,
113
- typeof ( object )
114
- ) ,
115
- providerParameter ,
116
- expressionParameter
117
- ) ;
118
- executeDelegate = lambdaExpression . Compile ( ) ;
119
- __executeDelegates . Add ( type , executeDelegate ) ;
120
- }
121
- return executeDelegate ;
122
- }
123
- }
124
-
125
50
// public methods
126
51
/// <summary>
127
52
/// Creates a new instance of MongoQueryable{{T}} for this provider.
@@ -154,11 +79,11 @@ public IQueryable CreateQuery(Expression expression)
154
79
{
155
80
throw new ArgumentNullException ( "expression" ) ;
156
81
}
82
+ var elementType = TypeSystem . GetElementType ( expression . Type ) ;
157
83
try
158
84
{
159
- var elementType = TypeSystem . GetElementType ( expression . Type ) ;
160
- var createQueryDelegate = GetCreateQueryDelegate ( elementType ) ;
161
- return createQueryDelegate ( this , expression ) ;
85
+ var queryableType = typeof ( MongoQueryable < > ) . MakeGenericType ( elementType ) ;
86
+ return ( IQueryable ) Activator . CreateInstance ( queryableType , new object [ ] { this , expression } ) ;
162
87
}
163
88
catch ( TargetInvocationException ex )
164
89
{
@@ -182,8 +107,7 @@ public TResult Execute<TResult>(Expression expression)
182
107
{
183
108
throw new ArgumentException ( "Argument expression is not valid." ) ;
184
109
}
185
- var translatedQuery = MongoQueryTranslator . Translate ( _collection , expression ) ;
186
- return ( TResult ) translatedQuery . Execute ( ) ;
110
+ return ( TResult ) Execute ( expression ) ;
187
111
}
188
112
189
113
/// <summary>
@@ -197,36 +121,8 @@ public object Execute(Expression expression)
197
121
{
198
122
throw new ArgumentNullException ( "expression" ) ;
199
123
}
200
- try
201
- {
202
- var resultType = expression . Type ;
203
- var executeDelegate = GetExecuteDelegate ( resultType ) ;
204
- return executeDelegate ( this , expression ) ;
205
- }
206
- catch ( TargetInvocationException ex )
207
- {
208
- throw ex . InnerException ;
209
- }
210
- }
211
-
212
- /// <summary>
213
- /// Gets an enumerator by executing the query.
214
- /// </summary>
215
- /// <typeparam name="T">Type element type.</typeparam>
216
- /// <param name="expression">The LINQ expression.</param>
217
- /// <returns>An enumerator for the results of the query.</returns>
218
- public IEnumerator < T > GetEnumerator < T > ( Expression expression )
219
- {
220
- if ( expression == null )
221
- {
222
- throw new ArgumentNullException ( "expression" ) ;
223
- }
224
- if ( ! typeof ( IEnumerable < T > ) . IsAssignableFrom ( expression . Type ) )
225
- {
226
- throw new ArgumentException ( "Argument expression is not valid." ) ;
227
- }
228
124
var translatedQuery = MongoQueryTranslator . Translate ( _collection , expression ) ;
229
- return translatedQuery . GetEnumerator < T > ( ) ;
125
+ return translatedQuery . Execute ( ) ;
230
126
}
231
127
232
128
/// <summary>
0 commit comments