@@ -248,32 +248,73 @@ 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 or Invoke expression to extract its runtime value
252
252
/// </summary>
253
253
public static object FindValue ( Expression expression )
254
254
{
255
- if ( expression . NodeType == ExpressionType . Constant )
256
- return ( ( ConstantExpression ) expression ) . Value ;
257
-
258
- if ( expression . NodeType == ExpressionType . MemberAccess )
255
+ object value ;
256
+ switch ( expression . NodeType )
259
257
{
260
- var memberAccess = ( MemberExpression ) expression ;
261
- if ( memberAccess . Expression == null || memberAccess . Expression . NodeType == ExpressionType . Constant )
262
- {
263
- var constantValue = ( ( ConstantExpression ) memberAccess . Expression ) ? . Value ;
264
- var member = memberAccess . Member ;
265
- switch ( member . MemberType )
258
+ case ExpressionType . Constant :
259
+ var constantExpression = ( ConstantExpression ) expression ;
260
+ return constantExpression . Value ;
261
+ case ExpressionType . MemberAccess :
262
+ var memberExpression = ( MemberExpression ) expression ;
263
+ value = memberExpression . Expression != null ? FindValue ( memberExpression . Expression ) : null ;
264
+
265
+ switch ( memberExpression . Member . MemberType )
266
266
{
267
267
case MemberTypes . Field :
268
- return ( ( FieldInfo ) member ) . GetValue ( constantValue ) ;
268
+ return ( ( FieldInfo ) memberExpression . Member ) . GetValue ( value ) ;
269
269
case MemberTypes . Property :
270
- return ( ( PropertyInfo ) member ) . GetValue ( constantValue ) ;
270
+ return ( ( PropertyInfo ) memberExpression . Member ) . GetValue ( value ) ;
271
271
}
272
- }
272
+ break ;
273
+ case ExpressionType . Call :
274
+ var methodCallExpression = ( MethodCallExpression ) expression ;
275
+ var args = new object [ methodCallExpression . Arguments . Count ] ;
276
+ for ( int i = 0 ; i < args . Length ; i ++ )
277
+ args [ i ] = FindValue ( methodCallExpression . Arguments [ i ] ) ;
278
+
279
+ if ( methodCallExpression . Object == null ) //extension or static method
280
+ {
281
+ if ( args . Length > 0 && args [ 0 ] != null )
282
+ {
283
+ return methodCallExpression . Method . Invoke ( args [ 0 ] . GetType ( ) , args ) ;
284
+ }
285
+ else
286
+ {
287
+ return methodCallExpression . Method . Invoke ( methodCallExpression . Method . DeclaringType , args ) ;
288
+ }
289
+ }
290
+ else
291
+ {
292
+ var callingObject = FindValue ( methodCallExpression . Object ) ;
293
+
294
+ return methodCallExpression . Method . Invoke ( callingObject , args ) ;
295
+ }
296
+ case ExpressionType . Convert :
297
+ var unaryExpression = ( UnaryExpression ) expression ;
298
+ value = FindValue ( unaryExpression . Operand ) ;
299
+ var type = Nullable . GetUnderlyingType ( unaryExpression . Type ) ?? unaryExpression . Type ;
300
+ if ( type == typeof ( object ) || value == null )
301
+ {
302
+ return value ;
303
+ }
304
+ else if ( value is IConvertible || unaryExpression . Method != null )
305
+ {
306
+ if ( type != unaryExpression . Operand . Type )
307
+ {
308
+ value = unaryExpression . Method != null ? unaryExpression . Method . Invoke ( null , new [ ] { value } ) : Convert . ChangeType ( value , type ) ;
309
+ }
310
+
311
+ return value ;
312
+ }
313
+ break ;
273
314
}
274
315
275
- var valueExpression = Expression . Lambda ( expression ) . Compile ( ) ;
276
- object value = valueExpression . DynamicInvoke ( ) ;
316
+ var valueExpression = Expression . Lambda ( expression ) . Compile ( true ) ;
317
+ value = valueExpression . DynamicInvoke ( ) ;
277
318
return value ;
278
319
}
279
320
0 commit comments