7
7
using System . Text . RegularExpressions ;
8
8
using NHibernate . Criterion ;
9
9
using NHibernate . Dialect . Function ;
10
+ using NHibernate . Engine ;
10
11
using NHibernate . Type ;
11
12
using NHibernate . Util ;
12
13
using Expression = System . Linq . Expressions . Expression ;
@@ -89,16 +90,18 @@ public Order CreateOrder(Func<string, Order> orderStringDelegate, Func<IProjecti
89
90
90
91
/// <summary>
91
92
/// Retrieve the property name from a supplied PropertyProjection
92
- /// Note: throws if the supplied IProjection is not a PropertyProjection
93
+ /// Note: throws if the supplied IProjection is not a IPropertyProjection
93
94
/// </summary>
94
95
public string AsProperty ( )
95
96
{
96
97
if ( _property != null ) return _property ;
97
98
98
- var propertyProjection = _projection as PropertyProjection ;
99
+ var propertyProjection = _projection as IPropertyProjection ;
99
100
if ( propertyProjection == null ) throw new InvalidOperationException ( "Cannot determine property for " + _projection ) ;
100
101
return propertyProjection . PropertyName ;
101
102
}
103
+
104
+ internal bool IsConstant ( out ConstantProjection value ) => ( value = _projection as ConstantProjection ) != null ;
102
105
}
103
106
104
107
private static readonly Dictionary < ExpressionType , Func < ProjectionInfo , object , ICriterion > > _simpleExpressionCreators ;
@@ -263,7 +266,8 @@ public static object FindValue(Expression expression)
263
266
public static ProjectionInfo FindMemberProjection ( Expression expression )
264
267
{
265
268
if ( ! IsMemberExpression ( expression ) )
266
- return AsArithmeticExpression ( expression ) ?? ProjectionInfo . ForProjection ( Projections . Constant ( FindValue ( expression ) ) ) ;
269
+ return AsArithmeticProjection ( expression )
270
+ ?? ProjectionInfo . ForProjection ( Projections . Constant ( FindValue ( expression ) , NHibernateUtil . GuessType ( expression . Type ) ) ) ;
267
271
268
272
var unwrapExpression = UnwrapConvertExpression ( expression ) ;
269
273
if ( unwrapExpression != null )
@@ -281,14 +285,14 @@ public static ProjectionInfo FindMemberProjection(Expression expression)
281
285
return ProjectionInfo . ForProjection ( processor ( methodCallExpression ) ) ;
282
286
}
283
287
}
284
- var memberExpression = expression as MemberExpression ;
285
- if ( memberExpression != null )
288
+ var memberExpression = expression as MemberExpression ;
289
+ if ( memberExpression != null )
286
290
{
287
- var signature = Signature ( memberExpression . Member ) ;
291
+ var signature = Signature ( memberExpression . Member ) ;
288
292
Func < Expression , IProjection > processor ;
289
293
if ( _customProjectionProcessors . TryGetValue ( signature , out processor ) )
290
294
{
291
- return ProjectionInfo . ForProjection ( processor ( memberExpression ) ) ;
295
+ return ProjectionInfo . ForProjection ( processor ( memberExpression ) ) ;
292
296
}
293
297
}
294
298
@@ -317,7 +321,7 @@ private static bool IsSupportedUnaryExpression(UnaryExpression expression)
317
321
return expression . NodeType == ExpressionType . Negate ;
318
322
}
319
323
320
- private static ProjectionInfo AsArithmeticExpression ( Expression expression )
324
+ private static ProjectionInfo AsArithmeticProjection ( Expression expression )
321
325
{
322
326
if ( ! ( expression is BinaryExpression be ) )
323
327
{
@@ -328,7 +332,7 @@ private static ProjectionInfo AsArithmeticExpression(Expression expression)
328
332
}
329
333
330
334
var unwrapExpression = UnwrapConvertExpression ( expression ) ;
331
- return unwrapExpression != null ? AsArithmeticExpression ( unwrapExpression ) : null ;
335
+ return unwrapExpression != null ? AsArithmeticProjection ( unwrapExpression ) : null ;
332
336
}
333
337
334
338
if ( ! _binaryArithmethicTemplates . TryGetValue ( be . NodeType , out var template ) )
@@ -565,21 +569,12 @@ private static object ConvertType(object value, System.Type type)
565
569
throw new ArgumentException ( string . Format ( "Cannot convert '{0}' to {1}" , value , type ) ) ;
566
570
}
567
571
568
- private static ICriterion ProcessSimpleExpression ( BinaryExpression be )
569
- {
570
- if ( be . Left . NodeType == ExpressionType . Call && ( ( MethodCallExpression ) be . Left ) . Method . Name == "CompareString" )
571
- return ProcessVisualBasicStringComparison ( be ) ;
572
-
573
- return ProcessSimpleExpression ( be . Left , be . Right , be . NodeType ) ;
574
- }
575
-
576
- private static ICriterion ProcessSimpleExpression ( Expression left , Expression right , ExpressionType nodeType )
572
+ private static ICriterion ProcessSimpleExpression ( Expression left , TypedValue rightValue , ExpressionType nodeType )
577
573
{
578
574
ProjectionInfo property = FindMemberProjection ( left ) ;
579
575
System . Type propertyType = FindMemberType ( left ) ;
580
576
581
- object value = FindValue ( right ) ;
582
- value = ConvertType ( value , propertyType ) ;
577
+ var value = ConvertType ( rightValue . Value , propertyType ) ;
583
578
584
579
if ( value == null )
585
580
return ProcessSimpleNullExpression ( property , nodeType ) ;
@@ -591,14 +586,17 @@ private static ICriterion ProcessSimpleExpression(Expression left, Expression ri
591
586
return simpleExpressionCreator ( property , value ) ;
592
587
}
593
588
594
- private static ICriterion ProcessVisualBasicStringComparison ( BinaryExpression be )
589
+ private static ICriterion ProcessAsVisualBasicStringComparison ( Expression left , ExpressionType nodeType )
595
590
{
596
- var methodCall = ( MethodCallExpression ) be . Left ;
591
+ if ( left . NodeType != ExpressionType . Call )
592
+ {
593
+ return null ;
594
+ }
597
595
598
- if ( IsMemberExpression ( methodCall . Arguments [ 1 ] ) )
599
- return ProcessMemberExpression ( methodCall . Arguments [ 0 ] , methodCall . Arguments [ 1 ] , be . NodeType ) ;
600
- else
601
- return ProcessSimpleExpression ( methodCall . Arguments [ 0 ] , methodCall . Arguments [ 1 ] , be . NodeType ) ;
596
+ var methodCall = ( MethodCallExpression ) left ;
597
+ return methodCall . Method . Name == "CompareString"
598
+ ? ProcessMemberExpression ( methodCall . Arguments [ 0 ] , methodCall . Arguments [ 1 ] , nodeType )
599
+ : null ;
602
600
}
603
601
604
602
private static ICriterion ProcessSimpleNullExpression ( ProjectionInfo property , ExpressionType expressionType )
@@ -613,15 +611,15 @@ private static ICriterion ProcessSimpleNullExpression(ProjectionInfo property, E
613
611
throw new ArgumentException ( "Cannot supply null value to operator " + expressionType , nameof ( expressionType ) ) ;
614
612
}
615
613
616
- private static ICriterion ProcessMemberExpression ( BinaryExpression be )
617
- {
618
- return ProcessMemberExpression ( be . Left , be . Right , be . NodeType ) ;
619
- }
620
-
621
614
private static ICriterion ProcessMemberExpression ( Expression left , Expression right , ExpressionType nodeType )
622
615
{
623
616
ProjectionInfo leftProperty = FindMemberProjection ( left ) ;
624
617
ProjectionInfo rightProperty = FindMemberProjection ( right ) ;
618
+ if ( rightProperty . IsConstant ( out var constProjection ) )
619
+ {
620
+ return ProcessAsVisualBasicStringComparison ( left , nodeType )
621
+ ?? ProcessSimpleExpression ( left , constProjection . TypedValue , nodeType ) ;
622
+ }
625
623
626
624
Func < ProjectionInfo , ProjectionInfo , ICriterion > propertyExpressionCreator ;
627
625
if ( ! _propertyExpressionCreators . TryGetValue ( nodeType , out propertyExpressionCreator ) )
@@ -660,11 +658,7 @@ private static ICriterion ProcessBinaryExpression(BinaryExpression expression)
660
658
case ExpressionType . GreaterThanOrEqual :
661
659
case ExpressionType . LessThan :
662
660
case ExpressionType . LessThanOrEqual :
663
- if ( IsMemberExpression ( expression . Right ) )
664
- return ProcessMemberExpression ( expression ) ;
665
- else
666
- return ProcessSimpleExpression ( expression ) ;
667
-
661
+ return ProcessMemberExpression ( expression . Left , expression . Right , expression . NodeType ) ;
668
662
default :
669
663
throw new NotImplementedException ( "Unhandled binary expression: " + expression . NodeType + ", " + expression ) ;
670
664
}
0 commit comments