11/******************************************************************************************************
22 Title : ExpressionEvaluator (https://github.com/codingseb/ExpressionEvaluator)
3- Version : 1.4.9 .0
3+ Version : 1.4.10 .0
44 (if last digit (the forth) is not a zero, the version is an intermediate version and can be unstable)
55
66 Author : Coding Seb
@@ -212,28 +212,39 @@ protected enum TryBlockEvaluatedState
212212 protected virtual IList < ExpressionOperator > RightOperandOnlyOperatorsEvaluationDictionary => rightOperandOnlyOperatorsEvaluationDictionary ;
213213 protected virtual IList < IDictionary < ExpressionOperator , Func < dynamic , dynamic , object > > > OperatorsEvaluations => operatorsEvaluations ;
214214
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+
215234 protected static readonly IList < IDictionary < ExpressionOperator , Func < dynamic , dynamic , object > > > operatorsEvaluations =
216235 new List < IDictionary < ExpressionOperator , Func < dynamic , dynamic , object > > > ( )
217236 {
218237 new Dictionary < ExpressionOperator , Func < dynamic , dynamic , object > > ( )
219238 {
220- { ExpressionOperator . Indexing , ( dynamic left , dynamic right ) =>
239+ { ExpressionOperator . Indexing , IndexingOperatorFunc } ,
240+ { ExpressionOperator . IndexingWithNullConditional , ( dynamic left , dynamic right ) =>
221241 {
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 ( ) ;
232244
233- return left [ right ] ;
245+ return IndexingOperatorFunc ( left , right ) ;
234246 }
235247 } ,
236- { ExpressionOperator . IndexingWithNullConditional , ( dynamic left , dynamic right ) => left is IDictionary < string , object > dictionaryLeft ? dictionaryLeft [ right ] : left ? [ right ] } ,
237248 } ,
238249 new Dictionary < ExpressionOperator , Func < dynamic , dynamic , object > > ( )
239250 {
@@ -358,7 +369,6 @@ protected enum TryBlockEvaluatedState
358369 return null ;
359370 }
360371 } ,
361- //{ "if", (self, args) => (bool)self.Evaluate(args[0]) ? self.Evaluate(args[1]) : self.Evaluate(args[2]) },
362372 { "in" , ( self , args ) => args . Skip ( 1 ) . ToList ( ) . ConvertAll ( self . Evaluate ) . Contains ( self . Evaluate ( args [ 0 ] ) ) } ,
363373 { "List" , ( self , args ) => args . ConvertAll ( self . Evaluate ) } ,
364374 { "ListOfType" , ( self , args ) =>
@@ -1787,7 +1797,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
17871797 object obj = inObject ? stack . Pop ( ) : Context ;
17881798 object keepObj = obj ;
17891799 Type objType = null ;
1790- Type [ ] inferedGenericsTypes = obj . GetType ( ) . GenericTypeArguments ;
1800+ Type [ ] inferedGenericsTypes = obj ? . GetType ( ) . GenericTypeArguments ;
17911801 ValueTypeNestingTrace valueTypeNestingTrace = null ;
17921802
17931803 if ( obj != null && TypesToBlock . Contains ( obj . GetType ( ) ) )
@@ -1799,9 +1809,13 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
17991809
18001810 try
18011811 {
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 )
18031817 {
1804- stack . Push ( null ) ;
1818+ stack . Push ( new NullConditionalNullValue ( ) ) ;
18051819 }
18061820 else
18071821 {
@@ -1977,9 +1991,13 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
19771991
19781992 try
19791993 {
1980- if ( varFuncMatch . Groups [ "nullConditional" ] . Success && obj == null )
1994+ if ( obj is NullConditionalNullValue )
19811995 {
1982- stack . Push ( null ) ;
1996+ stack . Push ( obj ) ;
1997+ }
1998+ else if ( varFuncMatch . Groups [ "nullConditional" ] . Success && obj == null )
1999+ {
2000+ stack . Push ( new NullConditionalNullValue ( ) ) ;
19832001 }
19842002 else
19852003 {
@@ -2544,9 +2562,17 @@ protected virtual bool EvaluateIndexing(string expression, Stack<object> stack,
25442562 throw new Exception ( $ "{ bracketCount } ']' character { beVerb } missing in expression : [{ expression } ]") ;
25452563 }
25462564
2565+ dynamic left = stack . Pop ( ) ;
2566+
2567+ if ( left is NullConditionalNullValue )
2568+ {
2569+ stack . Push ( left ) ;
2570+ return true ;
2571+ }
2572+
25472573 dynamic right = Evaluate ( innerExp . ToString ( ) ) ;
25482574 ExpressionOperator op = indexingBeginningMatch . Length == 2 ? ExpressionOperator . IndexingWithNullConditional : ExpressionOperator . Indexing ;
2549- dynamic left = stack . Pop ( ) ;
2575+
25502576
25512577 if ( OptionForceIntegerNumbersEvaluationsAsDoubleByDefault && right is double && Regex . IsMatch ( innerExp . ToString ( ) , @"^\d+$" ) )
25522578 right = ( int ) right ;
@@ -2566,7 +2592,7 @@ protected virtual bool EvaluateIndexing(string expression, Stack<object> stack,
25662592 throw new ExpressionEvaluatorSyntaxErrorException ( $ "The left part of { exceptionContext } must be a variable, a property or an indexer.") ;
25672593
25682594 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 } ") ;
25702596
25712597 if ( postFixOperator )
25722598 {
@@ -2752,6 +2778,7 @@ protected virtual object ProcessStack(Stack<object> stack)
27522778 List < object > list = stack
27532779 . Select ( e => e is ValueTypeNestingTrace valueTypeNestingTrace ? valueTypeNestingTrace . Value : e )
27542780 . Select ( e => e is SubExpression subExpression ? Evaluate ( subExpression . Expression ) : e )
2781+ . Select ( e => e is NullConditionalNullValue ? null : e )
27552782 . ToList ( ) ;
27562783
27572784 OperatorsEvaluations . ToList ( ) . ForEach ( ( IDictionary < ExpressionOperator , Func < dynamic , dynamic , object > > operatorEvalutationsDict ) =>
@@ -3400,7 +3427,7 @@ protected virtual string GetCodeUntilEndOfStringInterpolation(string subExpr)
34003427
34013428 #endregion
34023429
3403- #region Utils private sub classes for parsing and interpretation
3430+ #region Utils protected sub classes for parsing and interpretation
34043431
34053432 protected class ValueTypeNestingTrace
34063433 {
@@ -3424,6 +3451,9 @@ public void AssignValue()
34243451 }
34253452 }
34263453
3454+ protected class NullConditionalNullValue
3455+ { }
3456+
34273457 protected class DelegateEncaps
34283458 {
34293459 private readonly InternalDelegate lambda ;
0 commit comments