@@ -838,14 +838,28 @@ public IDictionary<string, object> Variables
838838 }
839839
840840 /// <summary>
841- /// Is Fired when no internal variable is found for a variable name.
841+ /// Is Fired before a variable, field or property resolution.
842+ /// Allow to define a variable and the corresponding value on the fly.
843+ /// Allow also to cancel the evaluation of this variable (consider it does'nt exists)
844+ /// </summary>
845+ public event EventHandler < VariablePreEvaluationEventArg > PreEvaluateVariable ;
846+
847+ /// <summary>
848+ /// Is Fired before a function or method resolution.
849+ /// Allow to define a function or method and the corresponding value on the fly.
850+ /// Allow also to cancel the evaluation of this function (consider it does'nt exists)
851+ /// </summary>
852+ public event EventHandler < FunctionPreEvaluationEventArg > PreEvaluateFunction ;
853+
854+ /// <summary>
855+ /// Is Fired if no variable, field or property were found
842856 /// Allow to define a variable and the corresponding value on the fly.
843857 /// </summary>
844858 public event EventHandler < VariableEvaluationEventArg > EvaluateVariable ;
845859
846860 /// <summary>
847- /// Is Fired when no internal function is found for a variable name .
848- /// Allow to define a function and the corresponding value on the fly.
861+ /// Is Fired if no function or method when were found .
862+ /// Allow to define a function or method and the corresponding value on the fly.
849863 /// </summary>
850864 public event EventHandler < FunctionEvaluationEventArg > EvaluateFunction ;
851865
@@ -1766,13 +1780,17 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
17661780 }
17671781 else
17681782 {
1769- FunctionEvaluationEventArg functionEvaluationEventArg = new FunctionEvaluationEventArg ( varFuncName , Evaluate , funcArgs , this , obj , genericsTypes , GetConcreteTypes ) ;
1783+ FunctionPreEvaluationEventArg functionPreEvaluationEventArg = new FunctionPreEvaluationEventArg ( varFuncName , Evaluate , funcArgs , this , obj , genericsTypes , GetConcreteTypes ) ;
17701784
1771- EvaluateFunction ? . Invoke ( this , functionEvaluationEventArg ) ;
1785+ PreEvaluateFunction ? . Invoke ( this , functionPreEvaluationEventArg ) ;
17721786
1773- if ( functionEvaluationEventArg . FunctionReturnedValue )
1787+ if ( functionPreEvaluationEventArg . CancelEvaluation )
17741788 {
1775- stack . Push ( functionEvaluationEventArg . Value ) ;
1789+ throw new ExpressionEvaluatorSyntaxErrorException ( $ "[{ objType } ] object has no Method named \" { varFuncName } \" .") ;
1790+ }
1791+ else if ( functionPreEvaluationEventArg . FunctionReturnedValue )
1792+ {
1793+ stack . Push ( functionPreEvaluationEventArg . Value ) ;
17761794 }
17771795 else
17781796 {
@@ -1802,22 +1820,26 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
18021820 }
18031821 else
18041822 {
1823+ bool isExtention = false ;
1824+
18051825 // if not found try to Find extension methods.
18061826 if ( methodInfo == null && obj != null )
18071827 {
18081828 oArgs . Insert ( 0 , obj ) ;
18091829 objType = obj . GetType ( ) ;
1810- obj = null ;
1830+ //obj = null;
1831+ object extentionObj = null ;
18111832 for ( int e = 0 ; e < StaticTypesForExtensionsMethods . Count && methodInfo == null ; e ++ )
18121833 {
18131834 Type type = StaticTypesForExtensionsMethods [ e ] ;
1814- methodInfo = GetRealMethod ( ref type , ref obj , varFuncName , StaticBindingFlag , oArgs , genericsTypes ) ;
1835+ methodInfo = GetRealMethod ( ref type , ref extentionObj , varFuncName , StaticBindingFlag , oArgs , genericsTypes ) ;
1836+ isExtention = methodInfo != null ;
18151837 }
18161838 }
18171839
18181840 if ( methodInfo != null )
18191841 {
1820- stack . Push ( methodInfo . Invoke ( obj , oArgs . ToArray ( ) ) ) ;
1842+ stack . Push ( methodInfo . Invoke ( isExtention ? null : obj , oArgs . ToArray ( ) ) ) ;
18211843 }
18221844 else if ( objType . GetProperty ( varFuncName , StaticBindingFlag ) is PropertyInfo staticPropertyInfo
18231845 && ( staticPropertyInfo . PropertyType . IsSubclassOf ( typeof ( Delegate ) ) || staticPropertyInfo . PropertyType == typeof ( Delegate ) ) )
@@ -1826,7 +1848,16 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
18261848 }
18271849 else
18281850 {
1829- throw new ExpressionEvaluatorSyntaxErrorException ( $ "[{ objType } ] object has no Method named \" { varFuncName } \" .") ;
1851+ FunctionEvaluationEventArg functionEvaluationEventArg = new FunctionEvaluationEventArg ( varFuncName , Evaluate , funcArgs , this , obj , genericsTypes , GetConcreteTypes ) ;
1852+
1853+ EvaluateFunction ? . Invoke ( this , functionEvaluationEventArg ) ;
1854+
1855+ if ( functionEvaluationEventArg . FunctionReturnedValue )
1856+ {
1857+ stack . Push ( functionEvaluationEventArg . Value ) ;
1858+ }
1859+ else
1860+ throw new ExpressionEvaluatorSyntaxErrorException ( $ "[{ objType } ] object has no Method named \" { varFuncName } \" .") ;
18301861 }
18311862 }
18321863 }
@@ -1846,31 +1877,46 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
18461877 }
18471878 }
18481879 }
1849- else if ( DefaultFunctions ( varFuncName , funcArgs , out object funcResult ) )
1850- {
1851- stack . Push ( funcResult ) ;
1852- }
1853- else if ( Variables . TryGetValue ( varFuncName , out object o ) && o is InternalDelegate lambdaExpression )
1854- {
1855- stack . Push ( lambdaExpression . Invoke ( funcArgs . ConvertAll ( e => Evaluate ( e ) ) . ToArray ( ) ) ) ;
1856- }
1857- else if ( Variables . TryGetValue ( varFuncName , out o ) && o is Delegate delegateVar )
1858- {
1859- stack . Push ( delegateVar . DynamicInvoke ( funcArgs . ConvertAll ( e => Evaluate ( e ) ) . ToArray ( ) ) ) ;
1860- }
18611880 else
18621881 {
1863- FunctionEvaluationEventArg functionEvaluationEventArg = new FunctionEvaluationEventArg ( varFuncName , Evaluate , funcArgs , this , genericTypes : genericsTypes , evaluateGenericTypes : GetConcreteTypes ) ;
1882+ FunctionPreEvaluationEventArg functionPreEvaluationEventArg = new FunctionPreEvaluationEventArg ( varFuncName , Evaluate , funcArgs , this , null , genericsTypes , GetConcreteTypes ) ;
18641883
1865- EvaluateFunction ? . Invoke ( this , functionEvaluationEventArg ) ;
1884+ PreEvaluateFunction ? . Invoke ( this , functionPreEvaluationEventArg ) ;
18661885
1867- if ( functionEvaluationEventArg . FunctionReturnedValue )
1886+ if ( functionPreEvaluationEventArg . CancelEvaluation )
1887+ {
1888+ throw new ExpressionEvaluatorSyntaxErrorException ( $ "Function [{ varFuncName } ] unknown in expression : [{ expr . Replace ( "\r " , "" ) . Replace ( "\n " , "" ) } ]") ;
1889+ }
1890+ else if ( functionPreEvaluationEventArg . FunctionReturnedValue )
1891+ {
1892+ stack . Push ( functionPreEvaluationEventArg . Value ) ;
1893+ }
1894+ else if ( DefaultFunctions ( varFuncName , funcArgs , out object funcResult ) )
1895+ {
1896+ stack . Push ( funcResult ) ;
1897+ }
1898+ else if ( Variables . TryGetValue ( varFuncName , out object o ) && o is InternalDelegate lambdaExpression )
1899+ {
1900+ stack . Push ( lambdaExpression . Invoke ( funcArgs . ConvertAll ( e => Evaluate ( e ) ) . ToArray ( ) ) ) ;
1901+ }
1902+ else if ( Variables . TryGetValue ( varFuncName , out o ) && o is Delegate delegateVar )
18681903 {
1869- stack . Push ( functionEvaluationEventArg . Value ) ;
1904+ stack . Push ( delegateVar . DynamicInvoke ( funcArgs . ConvertAll ( e => Evaluate ( e ) ) . ToArray ( ) ) ) ;
18701905 }
18711906 else
18721907 {
1873- throw new ExpressionEvaluatorSyntaxErrorException ( $ "Function [{ varFuncName } ] unknown in expression : [{ expr . Replace ( "\r " , "" ) . Replace ( "\n " , "" ) } ]") ;
1908+ FunctionEvaluationEventArg functionEvaluationEventArg = new FunctionEvaluationEventArg ( varFuncName , Evaluate , funcArgs , this , genericTypes : genericsTypes , evaluateGenericTypes : GetConcreteTypes ) ;
1909+
1910+ EvaluateFunction ? . Invoke ( this , functionEvaluationEventArg ) ;
1911+
1912+ if ( functionEvaluationEventArg . FunctionReturnedValue )
1913+ {
1914+ stack . Push ( functionEvaluationEventArg . Value ) ;
1915+ }
1916+ else
1917+ {
1918+ throw new ExpressionEvaluatorSyntaxErrorException ( $ "Function [{ varFuncName } ] unknown in expression : [{ expr . Replace ( "\r " , "" ) . Replace ( "\n " , "" ) } ]") ;
1919+ }
18741920 }
18751921 }
18761922 }
@@ -1971,13 +2017,17 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
19712017 }
19722018 else
19732019 {
1974- VariableEvaluationEventArg variableEvaluationEventArg = new VariableEvaluationEventArg ( varFuncName , this , obj , genericsTypes , GetConcreteTypes ) ;
2020+ VariablePreEvaluationEventArg variablePreEvaluationEventArg = new VariablePreEvaluationEventArg ( varFuncName , this , obj , genericsTypes , GetConcreteTypes ) ;
19752021
1976- EvaluateVariable ? . Invoke ( this , variableEvaluationEventArg ) ;
2022+ PreEvaluateVariable ? . Invoke ( this , variablePreEvaluationEventArg ) ;
19772023
1978- if ( variableEvaluationEventArg . HasValue )
2024+ if ( variablePreEvaluationEventArg . CancelEvaluation )
19792025 {
1980- stack . Push ( variableEvaluationEventArg . Value ) ;
2026+ throw new ExpressionEvaluatorSyntaxErrorException ( $ "[{ objType } ] object has no public Property or Member named \" { varFuncName } \" .", new Exception ( "Variable evaluation canceled" ) ) ;
2027+ }
2028+ else if ( variablePreEvaluationEventArg . HasValue )
2029+ {
2030+ stack . Push ( variablePreEvaluationEventArg . Value ) ;
19812031 }
19822032 else
19832033 {
@@ -2003,11 +2053,24 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
20032053 if ( isDynamic )
20042054 {
20052055 if ( ! varFuncMatch . Groups [ "assignationOperator" ] . Success || varFuncMatch . Groups [ "assignmentPrefix" ] . Success )
2006- varValue = dictionaryObject [ varFuncName ] ;
2056+ varValue = dictionaryObject . ContainsKey ( varFuncName ) ? dictionaryObject [ varFuncName ] : null ;
20072057 else
20082058 pushVarValue = false ;
20092059 }
2010- else
2060+
2061+ if ( member == null && pushVarValue )
2062+ {
2063+ VariableEvaluationEventArg variableEvaluationEventArg = new VariableEvaluationEventArg ( varFuncName , this , obj , genericsTypes , GetConcreteTypes ) ;
2064+
2065+ EvaluateVariable ? . Invoke ( this , variableEvaluationEventArg ) ;
2066+
2067+ if ( variableEvaluationEventArg . HasValue )
2068+ {
2069+ varValue = variableEvaluationEventArg . Value ;
2070+ }
2071+ }
2072+
2073+ if ( varValue == null && pushVarValue )
20112074 {
20122075 varValue = ( ( dynamic ) member ) . GetValue ( obj ) ;
20132076
@@ -2111,13 +2174,17 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
21112174 }
21122175 else
21132176 {
2114- VariableEvaluationEventArg variableEvaluationEventArg = new VariableEvaluationEventArg ( varFuncName , this , genericTypes : genericsTypes , evaluateGenericTypes : GetConcreteTypes ) ;
2177+ VariablePreEvaluationEventArg variablePreEvaluationEventArg = new VariablePreEvaluationEventArg ( varFuncName , this , genericTypes : genericsTypes , evaluateGenericTypes : GetConcreteTypes ) ;
21152178
2116- EvaluateVariable ? . Invoke ( this , variableEvaluationEventArg ) ;
2179+ PreEvaluateVariable ? . Invoke ( this , variablePreEvaluationEventArg ) ;
21172180
2118- if ( variableEvaluationEventArg . HasValue )
2181+ if ( variablePreEvaluationEventArg . CancelEvaluation )
2182+ {
2183+ throw new ExpressionEvaluatorSyntaxErrorException ( $ "Variable [{ varFuncName } ] unknown in expression : [{ expr } ]") ;
2184+ }
2185+ else if ( variablePreEvaluationEventArg . HasValue )
21192186 {
2120- stack . Push ( variableEvaluationEventArg . Value ) ;
2187+ stack . Push ( variablePreEvaluationEventArg . Value ) ;
21212188 }
21222189 else
21232190 {
@@ -2162,7 +2229,18 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
21622229 }
21632230 else
21642231 {
2165- throw new ExpressionEvaluatorSyntaxErrorException ( $ "Variable [{ varFuncName } ] unknown in expression : [{ expr } ]") ;
2232+ VariableEvaluationEventArg variableEvaluationEventArg = new VariableEvaluationEventArg ( varFuncName , this , genericTypes : genericsTypes , evaluateGenericTypes : GetConcreteTypes ) ;
2233+
2234+ EvaluateVariable ? . Invoke ( this , variableEvaluationEventArg ) ;
2235+
2236+ if ( variableEvaluationEventArg . HasValue )
2237+ {
2238+ stack . Push ( variableEvaluationEventArg . Value ) ;
2239+ }
2240+ else
2241+ {
2242+ throw new ExpressionEvaluatorSyntaxErrorException ( $ "Variable [{ varFuncName } ] unknown in expression : [{ expr } ]") ;
2243+ }
21662244 }
21672245 }
21682246 }
@@ -3393,6 +3471,18 @@ public Type[] EvaluateGenericTypes()
33933471 }
33943472 }
33953473
3474+ public class VariablePreEvaluationEventArg : VariableEvaluationEventArg
3475+ {
3476+ public VariablePreEvaluationEventArg ( string name , ExpressionEvaluator evaluator = null , object onInstance = null , string genericTypes = null , Func < string , Type [ ] > evaluateGenericTypes = null )
3477+ : base ( name , evaluator , onInstance , genericTypes , evaluateGenericTypes )
3478+ { }
3479+
3480+ /// <summary>
3481+ /// If set to true cancel the evaluation of the current variable, field or property and throw an exception it does not exists
3482+ /// </summary>
3483+ public bool CancelEvaluation { get ; set ; } = false ;
3484+ }
3485+
33963486 public partial class FunctionEvaluationEventArg : EventArgs
33973487 {
33983488 private readonly Func < string , object > evaluateFunc = null ;
@@ -3503,5 +3593,17 @@ public Type[] EvaluateGenericTypes()
35033593 }
35043594 }
35053595
3596+ public class FunctionPreEvaluationEventArg : FunctionEvaluationEventArg
3597+ {
3598+ public FunctionPreEvaluationEventArg ( string name , Func < string , object > evaluateFunc , List < string > args = null , ExpressionEvaluator evaluator = null , object onInstance = null , string genericTypes = null , Func < string , Type [ ] > evaluateGenericTypes = null )
3599+ : base ( name , evaluateFunc , args , evaluator , onInstance , genericTypes , evaluateGenericTypes )
3600+ { }
3601+
3602+ /// <summary>
3603+ /// If set to true cancel the evaluation of the current function or method and throw an exception that the function does not exists
3604+ /// </summary>
3605+ public bool CancelEvaluation { get ; set ; } = false ;
3606+ }
3607+
35063608 #endregion
35073609}
0 commit comments