7
7
using NHibernate . Linq ;
8
8
using NHibernate . Linq . Expressions ;
9
9
using NHibernate . Linq . Functions ;
10
+ using NHibernate . Linq . Visitors ;
10
11
using NHibernate . Persister . Collection ;
11
12
using NHibernate . Persister . Entity ;
12
13
using NHibernate . Type ;
@@ -33,7 +34,7 @@ internal static string TryGetEntityName(
33
34
out string memberPath ,
34
35
out IType memberType )
35
36
{
36
- var memberPaths = TryGetAllMemberMetadata ( expression , out var entityName , out var convertType ) ;
37
+ var memberPaths = MemberMetadataExtractor . TryGetAllMemberMetadata ( expression , out var entityName , out var convertType ) ;
37
38
if ( memberPaths == null )
38
39
{
39
40
memberPath = null ;
@@ -153,81 +154,6 @@ internal static string TryGetEntityName(
153
154
}
154
155
}
155
156
156
- private static Stack < MemberMetadata > TryGetAllMemberMetadata (
157
- Expression expression ,
158
- out string entityName ,
159
- out System . Type convertType )
160
- {
161
- var memberPaths = new Stack < MemberMetadata > ( ) ;
162
- var currentExpression = expression ;
163
- convertType = null ;
164
- bool hasIndexer = false ;
165
- while ( true )
166
- {
167
- if ( currentExpression is MemberExpression subMemberExpression )
168
- {
169
- memberPaths . Push ( new MemberMetadata ( subMemberExpression . Member . Name , convertType , hasIndexer ) ) ;
170
- convertType = null ;
171
- hasIndexer = false ;
172
- currentExpression = subMemberExpression . Expression ;
173
- }
174
- else if ( currentExpression is QuerySourceReferenceExpression querySourceReferenceExpression )
175
- {
176
- if ( querySourceReferenceExpression . ReferencedQuerySource is IFromClause fromClause )
177
- {
178
- currentExpression = fromClause . FromExpression ;
179
- }
180
- else if ( querySourceReferenceExpression . ReferencedQuerySource is JoinClause joinClause )
181
- {
182
- currentExpression = joinClause . InnerSequence ;
183
- }
184
- else
185
- {
186
- // Unknown ReferencedQuerySource
187
- entityName = null ;
188
- return null ;
189
- }
190
- }
191
- else if ( currentExpression is UnaryExpression unaryExpression ) // ((BaseEntity)q.Entity).Prop
192
- {
193
- currentExpression = unaryExpression . Operand ;
194
- convertType = unaryExpression . Type ;
195
- }
196
- else if ( currentExpression is NhNominatedExpression nominatedExpression ) // ((BaseEntity)q.Entity).Prop
197
- {
198
- currentExpression = nominatedExpression . Expression ;
199
- }
200
- else if ( currentExpression is ConstantExpression constantExpression )
201
- {
202
- if ( ! ( constantExpression . Value is IEntityNameProvider entityNameProvider ) )
203
- {
204
- // Not a NhQueryable<T>
205
- entityName = null ;
206
- return null ;
207
- }
208
-
209
- entityName = entityNameProvider . EntityName ;
210
- break ;
211
- }
212
- else if ( currentExpression is MethodCallExpression methodCallExpression &&
213
- ListIndexerGenerator . IsMethodSupported ( methodCallExpression . Method ) )
214
- {
215
- currentExpression = methodCallExpression . Object == null
216
- ? Enumerable . First ( methodCallExpression . Arguments ) // q.Children.ElementAt(0)
217
- : methodCallExpression . Object ; // q.Children[0]
218
- hasIndexer = true ;
219
- }
220
- else
221
- {
222
- // Not supported expressions
223
- entityName = null ;
224
- return null ;
225
- }
226
- }
227
-
228
- return memberPaths ;
229
- }
230
-
231
157
private static string GetEntityName (
232
158
string currentEntityName ,
233
159
System . Type convertedType ,
@@ -330,6 +256,100 @@ private static IType GetType(
330
256
return null ;
331
257
}
332
258
259
+ private class MemberMetadataExtractor : NhExpressionVisitor
260
+ {
261
+ private readonly Stack < MemberMetadata > _memberPaths = new Stack < MemberMetadata > ( ) ;
262
+ private System . Type _convertType ;
263
+ private bool _hasIndexer ;
264
+ private string _entityName ;
265
+
266
+ public static Stack < MemberMetadata > TryGetAllMemberMetadata (
267
+ Expression expression ,
268
+ out string entityName ,
269
+ out System . Type convertType )
270
+ {
271
+ var extractor = new MemberMetadataExtractor ( ) ;
272
+ extractor . Accept ( expression ) ;
273
+ entityName = extractor . _entityName ;
274
+ convertType = entityName != null ? extractor . _convertType : null ;
275
+ return entityName != null ? extractor . _memberPaths : null ;
276
+ }
277
+
278
+ private void Accept ( Expression expression )
279
+ {
280
+ base . Visit ( expression ) ;
281
+ }
282
+
283
+ protected override Expression VisitMember ( MemberExpression node )
284
+ {
285
+ _memberPaths . Push ( new MemberMetadata ( node . Member . Name , _convertType , _hasIndexer ) ) ;
286
+ _convertType = null ;
287
+ _hasIndexer = false ;
288
+ return base . Visit ( node . Expression ) ;
289
+ }
290
+
291
+ protected override Expression VisitQuerySourceReference ( QuerySourceReferenceExpression node )
292
+ {
293
+ if ( node . ReferencedQuerySource is IFromClause fromClause )
294
+ {
295
+ return base . Visit ( fromClause . FromExpression ) ;
296
+ }
297
+
298
+ if ( node . ReferencedQuerySource is JoinClause joinClause )
299
+ {
300
+ return base . Visit ( joinClause . InnerSequence ) ;
301
+ }
302
+
303
+ // Not supported expression
304
+ _entityName = null ;
305
+ return node ;
306
+ }
307
+
308
+ protected override Expression VisitUnary ( UnaryExpression node )
309
+ {
310
+ _convertType = node . Type ;
311
+ return base . Visit ( node . Operand ) ;
312
+ }
313
+
314
+ protected internal override Expression VisitNhNominated ( NhNominatedExpression node )
315
+ {
316
+ return base . Visit ( node ) ;
317
+ }
318
+
319
+ protected override Expression VisitConstant ( ConstantExpression node )
320
+ {
321
+ _entityName = node . Value is IEntityNameProvider entityNameProvider
322
+ ? entityNameProvider . EntityName
323
+ : null ; // Not a NhQueryable<T>
324
+
325
+ return node ;
326
+ }
327
+
328
+ protected override Expression VisitMethodCall ( MethodCallExpression node )
329
+ {
330
+ if ( ListIndexerGenerator . IsMethodSupported ( node . Method ) )
331
+ {
332
+ _hasIndexer = true ;
333
+ return base . Visit (
334
+ node . Object == null
335
+ ? Enumerable . First ( node . Arguments ) // q.Children.ElementAt(0)
336
+ : node . Object // q.Children[0]
337
+ ) ;
338
+ }
339
+
340
+ // Not supported expression
341
+ _entityName = null ;
342
+ return node ;
343
+ }
344
+
345
+ public override Expression Visit ( Expression node )
346
+ {
347
+ // Not supported expression
348
+ _entityName = null ;
349
+ return node ;
350
+ }
351
+ }
352
+
333
353
private struct MemberMetadata
334
354
{
335
355
public MemberMetadata ( string path , System . Type convertType , bool hasIndexer )
0 commit comments