@@ -248,7 +248,7 @@ private static ICriterion Le(ProjectionInfo property, object value)
248
248
}
249
249
250
250
/// <summary>
251
- /// Invoke the expression to extract its runtime value
251
+ /// Walk on expression extract its runtime value
252
252
/// </summary>
253
253
public static object FindValue ( Expression expression )
254
254
{
@@ -258,10 +258,10 @@ public static object FindValue(Expression expression)
258
258
if ( expression . NodeType == ExpressionType . MemberAccess )
259
259
{
260
260
var memberAccess = ( MemberExpression ) expression ;
261
+ var member = memberAccess . Member ;
261
262
if ( memberAccess . Expression == null || memberAccess . Expression . NodeType == ExpressionType . Constant )
262
263
{
263
264
var constantValue = ( ( ConstantExpression ) memberAccess . Expression ) ? . Value ;
264
- var member = memberAccess . Member ;
265
265
switch ( member . MemberType )
266
266
{
267
267
case MemberTypes . Field :
@@ -270,11 +270,90 @@ public static object FindValue(Expression expression)
270
270
return ( ( PropertyInfo ) member ) . GetValue ( constantValue ) ;
271
271
}
272
272
}
273
+ else
274
+ {
275
+ switch ( member . MemberType )
276
+ {
277
+ case MemberTypes . Field :
278
+ return ( ( FieldInfo ) member ) . GetValue ( FindValue ( memberAccess . Expression ) ) ;
279
+ case MemberTypes . Property :
280
+ return ( ( PropertyInfo ) member ) . GetValue ( FindValue ( memberAccess . Expression ) ) ;
281
+ }
282
+ }
283
+ }
284
+
285
+ if ( expression . NodeType == ExpressionType . Call )
286
+ {
287
+ var methodCall = ( MethodCallExpression ) expression ;
288
+
289
+ var args = new object [ methodCall . Arguments . Count ] ;
290
+ for ( int i = 0 ; i < args . Length ; i ++ )
291
+ args [ i ] = FindValue ( methodCall . Arguments [ i ] ) ;
292
+
293
+ if ( methodCall . Object == null ) //extension or static method
294
+ {
295
+ if ( args . Length > 0 && args [ 0 ] != null )
296
+ {
297
+ return methodCall . Method . Invoke ( args [ 0 ] . GetType ( ) , args ) ;
298
+ }
299
+ else
300
+ {
301
+ return methodCall . Method . Invoke ( methodCall . Method . DeclaringType , args ) ;
302
+ }
303
+ }
304
+ else
305
+ {
306
+ var callingObject = FindValue ( methodCall . Object ) ;
307
+
308
+ return methodCall . Method . Invoke ( callingObject , args ) ;
309
+ }
310
+ }
311
+
312
+ if ( expression . NodeType == ExpressionType . Convert )
313
+ {
314
+ var convert = ( UnaryExpression ) expression ;
315
+ var value = FindValue ( convert . Operand ) ;
316
+ if ( value != null )
317
+ {
318
+ var type = Nullable . GetUnderlyingType ( convert . Type ) ?? convert . Type ;
319
+ if ( type != convert . Operand . Type )
320
+ {
321
+ return convert . Method != null
322
+ ? convert . Method . Invoke ( null , new [ ] { value } )
323
+ : Convert . ChangeType ( value , type ) ;
324
+ }
325
+ }
326
+
327
+ return value ;
328
+ }
329
+
330
+ if ( expression is BinaryExpression binary )
331
+ {
332
+ dynamic left = FindValue ( binary . Left ) ;
333
+ dynamic right = FindValue ( binary . Right ) ;
334
+ if ( binary . Method != null )
335
+ {
336
+ return binary . Method . Invoke ( null , new [ ] { left , right } ) ;
337
+ }
338
+ else
339
+ {
340
+ switch ( expression . NodeType )
341
+ {
342
+ case ExpressionType . Multiply :
343
+ return left * right ;
344
+ case ExpressionType . Divide :
345
+ return left / right ;
346
+ case ExpressionType . Modulo :
347
+ return left % right ;
348
+ case ExpressionType . Add :
349
+ return left + right ;
350
+ case ExpressionType . Subtract :
351
+ return left - right ;
352
+ }
353
+ }
273
354
}
274
355
275
- var valueExpression = Expression . Lambda ( expression ) . Compile ( ) ;
276
- object value = valueExpression . DynamicInvoke ( ) ;
277
- return value ;
356
+ return Expression . Lambda ( expression ) . Compile ( ) . DynamicInvoke ( ) ;
278
357
}
279
358
280
359
/// <summary>
0 commit comments