1
1
/******************************************************************************************************
2
2
Title : ExpressionEvaluator (https://github.com/codingseb/ExpressionEvaluator)
3
- Version : 1.4.9 .0
3
+ Version : 1.4.10 .0
4
4
(if last digit (the forth) is not a zero, the version is an intermediate version and can be unstable)
5
5
6
6
Author : Coding Seb
@@ -212,28 +212,39 @@ protected enum TryBlockEvaluatedState
212
212
protected virtual IList < ExpressionOperator > RightOperandOnlyOperatorsEvaluationDictionary => rightOperandOnlyOperatorsEvaluationDictionary ;
213
213
protected virtual IList < IDictionary < ExpressionOperator , Func < dynamic , dynamic , object > > > OperatorsEvaluations => operatorsEvaluations ;
214
214
215
+ protected static object IndexingOperatorFunc ( dynamic left , dynamic right )
216
+ {
217
+ if ( left is NullConditionalNullValue )
218
+ return left ;
219
+
220
+ Type type = ( ( object ) left ) . GetType ( ) ;
221
+
222
+ if ( left is IDictionary < string , object > dictionaryLeft )
223
+ {
224
+ return dictionaryLeft [ right ] ;
225
+ }
226
+ else if ( type . GetMethod ( "Item" , new Type [ ] { ( ( object ) right ) . GetType ( ) } ) is MethodInfo methodInfo )
227
+ {
228
+ return methodInfo . Invoke ( left , new object [ ] { right } ) ;
229
+ }
230
+
231
+ return left [ right ] ;
232
+ }
233
+
215
234
protected static readonly IList < IDictionary < ExpressionOperator , Func < dynamic , dynamic , object > > > operatorsEvaluations =
216
235
new List < IDictionary < ExpressionOperator , Func < dynamic , dynamic , object > > > ( )
217
236
{
218
237
new Dictionary < ExpressionOperator , Func < dynamic , dynamic , object > > ( )
219
238
{
220
- { ExpressionOperator . Indexing , ( dynamic left , dynamic right ) =>
239
+ { ExpressionOperator . Indexing , IndexingOperatorFunc } ,
240
+ { ExpressionOperator . IndexingWithNullConditional , ( dynamic left , dynamic right ) =>
221
241
{
222
- Type type = ( ( object ) left ) . GetType ( ) ;
223
-
224
- if ( left is IDictionary < string , object > dictionaryLeft )
225
- {
226
- return dictionaryLeft [ right ] ;
227
- }
228
- else if ( type . GetMethod ( "Item" , new Type [ ] { ( ( object ) right ) . GetType ( ) } ) is MethodInfo methodInfo )
229
- {
230
- return methodInfo . Invoke ( left , new object [ ] { right } ) ;
231
- }
242
+ if ( left == null )
243
+ return new NullConditionalNullValue ( ) ;
232
244
233
- return left [ right ] ;
245
+ return IndexingOperatorFunc ( left , right ) ;
234
246
}
235
247
} ,
236
- { ExpressionOperator . IndexingWithNullConditional , ( dynamic left , dynamic right ) => left is IDictionary < string , object > dictionaryLeft ? dictionaryLeft [ right ] : left ? [ right ] } ,
237
248
} ,
238
249
new Dictionary < ExpressionOperator , Func < dynamic , dynamic , object > > ( )
239
250
{
@@ -358,7 +369,6 @@ protected enum TryBlockEvaluatedState
358
369
return null ;
359
370
}
360
371
} ,
361
- //{ "if", (self, args) => (bool)self.Evaluate(args[0]) ? self.Evaluate(args[1]) : self.Evaluate(args[2]) },
362
372
{ "in" , ( self , args ) => args . Skip ( 1 ) . ToList ( ) . ConvertAll ( self . Evaluate ) . Contains ( self . Evaluate ( args [ 0 ] ) ) } ,
363
373
{ "List" , ( self , args ) => args . ConvertAll ( self . Evaluate ) } ,
364
374
{ "ListOfType" , ( self , args ) =>
@@ -1787,7 +1797,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
1787
1797
object obj = inObject ? stack . Pop ( ) : Context ;
1788
1798
object keepObj = obj ;
1789
1799
Type objType = null ;
1790
- Type [ ] inferedGenericsTypes = obj . GetType ( ) . GenericTypeArguments ;
1800
+ Type [ ] inferedGenericsTypes = obj ? . GetType ( ) . GenericTypeArguments ;
1791
1801
ValueTypeNestingTrace valueTypeNestingTrace = null ;
1792
1802
1793
1803
if ( obj != null && TypesToBlock . Contains ( obj . GetType ( ) ) )
@@ -1799,9 +1809,13 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
1799
1809
1800
1810
try
1801
1811
{
1802
- if ( varFuncMatch . Groups [ "nullConditional" ] . Success && obj == null )
1812
+ if ( obj is NullConditionalNullValue )
1813
+ {
1814
+ stack . Push ( obj ) ;
1815
+ }
1816
+ else if ( varFuncMatch . Groups [ "nullConditional" ] . Success && obj == null )
1803
1817
{
1804
- stack . Push ( null ) ;
1818
+ stack . Push ( new NullConditionalNullValue ( ) ) ;
1805
1819
}
1806
1820
else
1807
1821
{
@@ -1977,9 +1991,13 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
1977
1991
1978
1992
try
1979
1993
{
1980
- if ( varFuncMatch . Groups [ "nullConditional" ] . Success && obj == null )
1994
+ if ( obj is NullConditionalNullValue )
1981
1995
{
1982
- stack . Push ( null ) ;
1996
+ stack . Push ( obj ) ;
1997
+ }
1998
+ else if ( varFuncMatch . Groups [ "nullConditional" ] . Success && obj == null )
1999
+ {
2000
+ stack . Push ( new NullConditionalNullValue ( ) ) ;
1983
2001
}
1984
2002
else
1985
2003
{
@@ -2544,9 +2562,17 @@ protected virtual bool EvaluateIndexing(string expression, Stack<object> stack,
2544
2562
throw new Exception ( $ "{ bracketCount } ']' character { beVerb } missing in expression : [{ expression } ]") ;
2545
2563
}
2546
2564
2565
+ dynamic left = stack . Pop ( ) ;
2566
+
2567
+ if ( left is NullConditionalNullValue )
2568
+ {
2569
+ stack . Push ( left ) ;
2570
+ return true ;
2571
+ }
2572
+
2547
2573
dynamic right = Evaluate ( innerExp . ToString ( ) ) ;
2548
2574
ExpressionOperator op = indexingBeginningMatch . Length == 2 ? ExpressionOperator . IndexingWithNullConditional : ExpressionOperator . Indexing ;
2549
- dynamic left = stack . Pop ( ) ;
2575
+
2550
2576
2551
2577
if ( OptionForceIntegerNumbersEvaluationsAsDoubleByDefault && right is double && Regex . IsMatch ( innerExp . ToString ( ) , @"^\d+$" ) )
2552
2578
right = ( int ) right ;
@@ -2566,7 +2592,7 @@ protected virtual bool EvaluateIndexing(string expression, Stack<object> stack,
2566
2592
throw new ExpressionEvaluatorSyntaxErrorException ( $ "The left part of { exceptionContext } must be a variable, a property or an indexer.") ;
2567
2593
2568
2594
if ( op == ExpressionOperator . IndexingWithNullConditional )
2569
- throw new ExpressionEvaluatorSyntaxErrorException ( $ "Null coalescing is not usable left to { exceptionContext } ") ;
2595
+ throw new ExpressionEvaluatorSyntaxErrorException ( $ "Null conditional is not usable left to { exceptionContext } ") ;
2570
2596
2571
2597
if ( postFixOperator )
2572
2598
{
@@ -2752,6 +2778,7 @@ protected virtual object ProcessStack(Stack<object> stack)
2752
2778
List < object > list = stack
2753
2779
. Select ( e => e is ValueTypeNestingTrace valueTypeNestingTrace ? valueTypeNestingTrace . Value : e )
2754
2780
. Select ( e => e is SubExpression subExpression ? Evaluate ( subExpression . Expression ) : e )
2781
+ . Select ( e => e is NullConditionalNullValue ? null : e )
2755
2782
. ToList ( ) ;
2756
2783
2757
2784
OperatorsEvaluations . ToList ( ) . ForEach ( ( IDictionary < ExpressionOperator , Func < dynamic , dynamic , object > > operatorEvalutationsDict ) =>
@@ -3400,7 +3427,7 @@ protected virtual string GetCodeUntilEndOfStringInterpolation(string subExpr)
3400
3427
3401
3428
#endregion
3402
3429
3403
- #region Utils private sub classes for parsing and interpretation
3430
+ #region Utils protected sub classes for parsing and interpretation
3404
3431
3405
3432
protected class ValueTypeNestingTrace
3406
3433
{
@@ -3424,6 +3451,9 @@ public void AssignValue()
3424
3451
}
3425
3452
}
3426
3453
3454
+ protected class NullConditionalNullValue
3455
+ { }
3456
+
3427
3457
protected class DelegateEncaps
3428
3458
{
3429
3459
private readonly InternalDelegate lambda ;
0 commit comments