11/******************************************************************************************************
22 Title : ExpressionEvaluator (https://github.com/codingseb/ExpressionEvaluator)
3- Version : 1.4.1 .0
3+ Version : 1.4.2 .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
@@ -452,11 +452,18 @@ public static void ClearAllCaches()
452452
453453 #region Assemblies, Namespaces and types lists
454454
455+ private static IList < Assembly > staticAssemblies ;
456+ private IList < Assembly > assemblies ;
457+
455458 /// <summary>
456459 /// All assemblies needed to resolves Types
457460 /// by default all Assemblies loaded in the current AppDomain
458461 /// </summary>
459- public virtual IList < Assembly > Assemblies { get ; set ; } = new List < Assembly > ( ) ;
462+ public virtual IList < Assembly > Assemblies
463+ {
464+ get { return assemblies ?? ( assemblies = staticAssemblies ) ?? ( assemblies = staticAssemblies = AppDomain . CurrentDomain . GetAssemblies ( ) . ToList ( ) ) ; }
465+ set { assemblies = value ; }
466+ }
460467
461468 /// <summary>
462469 /// All Namespaces Where to find types
@@ -848,8 +855,6 @@ public IDictionary<string, object> Variables
848855 /// </summary>
849856 public ExpressionEvaluator ( )
850857 {
851- AssembliesInit ( ) ;
852-
853858 DefaultDecimalSeparatorInit ( ) ;
854859
855860 Init ( ) ;
@@ -864,11 +869,6 @@ public ExpressionEvaluator(IDictionary<string, object> variables) : this()
864869 Variables = variables ;
865870 }
866871
867- protected virtual void AssembliesInit ( )
868- {
869- Assemblies = AppDomain . CurrentDomain . GetAssemblies ( ) . ToList ( ) ;
870- }
871-
872872 protected virtual void DefaultDecimalSeparatorInit ( )
873873 {
874874 numberRegexPattern = string . Format ( numberRegexOrigPattern , @"\." , string . Empty ) ;
@@ -1362,8 +1362,6 @@ void forAction(int index)
13621362 breakCalled = isBreak ;
13631363 continueCalled = isContinue ;
13641364
1365- inScript = false ;
1366-
13671365 if ( isReturn || OptionOnNoReturnKeywordFoundInScriptAction == OptionOnNoReturnKeywordFoundInScriptAction . ReturnAutomaticallyLastEvaluatedExpression )
13681366 return lastResult ;
13691367 else if ( OptionOnNoReturnKeywordFoundInScriptAction == OptionOnNoReturnKeywordFoundInScriptAction . ReturnNull )
@@ -1419,7 +1417,7 @@ public object Evaluate(string expression)
14191417
14201418 for ( int i = 0 ; i < expression . Length ; i ++ )
14211419 {
1422- if ( ! ParsingMethods . Any ( m => m ( expression , stack , ref i ) ) )
1420+ if ( ! ParsingMethods . Any ( parsingMethod => parsingMethod ( expression , stack , ref i ) ) )
14231421 {
14241422 string s = expression . Substring ( i , 1 ) ;
14251423
@@ -1735,6 +1733,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
17351733 object obj = stack . Pop ( ) ;
17361734 object keepObj = obj ;
17371735 Type objType = null ;
1736+ Type [ ] inferedGenericsTypes = obj . GetType ( ) . GenericTypeArguments ;
17381737 ValueTypeNestingTrace valueTypeNestingTrace = null ;
17391738
17401739 if ( obj != null && TypesToBlock . Contains ( obj . GetType ( ) ) )
@@ -1775,7 +1774,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
17751774 throw new ExpressionEvaluatorSyntaxErrorException ( $ "[{ objType } ] object has no Method named \" { varFuncName } \" .") ;
17761775
17771776 // Standard Instance or public method find
1778- MethodInfo methodInfo = GetRealMethod ( ref objType , ref obj , varFuncName , flag , oArgs , genericsTypes ) ;
1777+ MethodInfo methodInfo = GetRealMethod ( ref objType , ref obj , varFuncName , flag , oArgs , genericsTypes , inferedGenericsTypes ) ;
17791778
17801779 // if not found check if obj is an expandoObject or similar
17811780 if ( obj is IDynamicMetaObjectProvider
@@ -1807,7 +1806,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
18071806 for ( int e = 0 ; e < StaticTypesForExtensionsMethods . Count && methodInfo == null ; e ++ )
18081807 {
18091808 Type type = StaticTypesForExtensionsMethods [ e ] ;
1810- methodInfo = GetRealMethod ( ref type , ref extentionObj , varFuncName , StaticBindingFlag , oArgs , genericsTypes ) ;
1809+ methodInfo = GetRealMethod ( ref type , ref extentionObj , varFuncName , StaticBindingFlag , oArgs , genericsTypes , inferedGenericsTypes ) ;
18111810 isExtention = methodInfo != null ;
18121811 }
18131812 }
@@ -2042,17 +2041,14 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
20422041 {
20432042 dictionaryObject [ varFuncName ] = varValue ;
20442043 }
2044+ else if ( valueTypeNestingTrace != null )
2045+ {
2046+ valueTypeNestingTrace . Value = varValue ;
2047+ valueTypeNestingTrace . AssignValue ( ) ;
2048+ }
20452049 else
20462050 {
2047- if ( valueTypeNestingTrace != null )
2048- {
2049- valueTypeNestingTrace . Value = varValue ;
2050- valueTypeNestingTrace . AssignValue ( ) ;
2051- }
2052- else
2053- {
2054- ( ( dynamic ) member ) . SetValue ( obj , varValue ) ;
2055- }
2051+ ( ( dynamic ) member ) . SetValue ( obj , varValue ) ;
20562052 }
20572053 }
20582054 }
@@ -2756,21 +2752,33 @@ protected virtual bool GetLambdaExpression(string expression, Stack<object> stac
27562752
27572753 stack . Push ( new InternalDelegate ( ( object [ ] args ) =>
27582754 {
2759- Dictionary < string , object > vars = new Dictionary < string , object > ( Variables ) ;
2755+ var vars = new Dictionary < string , object > ( variables ) ;
27602756
27612757 for ( int a = 0 ; a < argsNames . Count || a < args . Length ; a ++ )
27622758 {
27632759 vars [ argsNames [ a ] ] = args [ a ] ;
27642760 }
27652761
2766- ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator ( vars ) ;
2762+ var savedVars = variables ;
2763+ Variables = vars ;
27672764
27682765 string lambdaBody = lambdaExpressionMatch . Groups [ "expression" ] . Value . Trim ( ) ;
27692766
2767+ object result = null ;
2768+
27702769 if ( inScript && lambdaBody . StartsWith ( "{" ) && lambdaBody . EndsWith ( "}" ) )
2771- return expressionEvaluator . ScriptEvaluate ( lambdaBody . Substring ( 1 , lambdaBody . Length - 2 ) ) ;
2770+ {
2771+ result = ScriptEvaluate ( lambdaBody . Substring ( 1 , lambdaBody . Length - 2 ) ) ;
2772+ inScript = true ;
2773+ }
27722774 else
2773- return expressionEvaluator . Evaluate ( lambdaExpressionMatch . Groups [ "expression" ] . Value ) ;
2775+ {
2776+ result = Evaluate ( lambdaExpressionMatch . Groups [ "expression" ] . Value ) ;
2777+ }
2778+
2779+ variables = savedVars ;
2780+
2781+ return result ;
27742782 } ) ) ;
27752783
27762784 return true ;
@@ -2781,7 +2789,7 @@ protected virtual bool GetLambdaExpression(string expression, Stack<object> stac
27812789 }
27822790 }
27832791
2784- protected virtual MethodInfo GetRealMethod ( ref Type type , ref object obj , string func , BindingFlags flag , List < object > args , string genericsTypes = "" )
2792+ protected virtual MethodInfo GetRealMethod ( ref Type type , ref object obj , string func , BindingFlags flag , List < object > args , string genericsTypes , Type [ ] inferedGenericsTypes )
27852793 {
27862794 MethodInfo methodInfo = null ;
27872795 List < object > modifiedArgs = new List < object > ( args ) ;
@@ -2790,7 +2798,7 @@ protected virtual MethodInfo GetRealMethod(ref Type type, ref object obj, string
27902798 && ( func . StartsWith ( "Fluid" , StringComparisonForCasing )
27912799 || func . StartsWith ( "Fluent" , StringComparisonForCasing ) ) )
27922800 {
2793- methodInfo = GetRealMethod ( ref type , ref obj , func . Substring ( func . StartsWith ( "Fluid" , StringComparisonForCasing ) ? 5 : 6 ) , flag , modifiedArgs , genericsTypes ) ;
2801+ methodInfo = GetRealMethod ( ref type , ref obj , func . Substring ( func . StartsWith ( "Fluid" , StringComparisonForCasing ) ? 5 : 6 ) , flag , modifiedArgs , genericsTypes , inferedGenericsTypes ) ;
27942802 if ( methodInfo != null )
27952803 {
27962804 if ( methodInfo . ReturnType == typeof ( void ) )
@@ -2818,7 +2826,7 @@ protected virtual MethodInfo GetRealMethod(ref Type type, ref object obj, string
28182826
28192827 if ( methodInfo != null )
28202828 {
2821- methodInfo = MakeConcreteMethodIfGeneric ( methodInfo , genericsTypes ) ;
2829+ methodInfo = MakeConcreteMethodIfGeneric ( methodInfo , genericsTypes , inferedGenericsTypes ) ;
28222830 }
28232831 else
28242832 {
@@ -2828,7 +2836,7 @@ protected virtual MethodInfo GetRealMethod(ref Type type, ref object obj, string
28282836
28292837 for ( int m = 0 ; m < methodInfos . Count && methodInfo == null ; m ++ )
28302838 {
2831- methodInfos [ m ] = MakeConcreteMethodIfGeneric ( methodInfos [ m ] , genericsTypes ) ;
2839+ methodInfos [ m ] = MakeConcreteMethodIfGeneric ( methodInfos [ m ] , genericsTypes , inferedGenericsTypes ) ;
28322840
28332841 bool parametersCastOK = true ;
28342842
@@ -2891,14 +2899,25 @@ protected virtual MethodInfo GetRealMethod(ref Type type, ref object obj, string
28912899 return methodInfo ;
28922900 }
28932901
2894- protected virtual MethodInfo MakeConcreteMethodIfGeneric ( MethodInfo methodInfo , string genericsTypes = "" )
2902+ protected virtual MethodInfo MakeConcreteMethodIfGeneric ( MethodInfo methodInfo , string genericsTypes , Type [ ] inferedGenericsTypes )
28952903 {
28962904 if ( methodInfo . IsGenericMethod )
28972905 {
28982906 if ( genericsTypes . Equals ( string . Empty ) )
2899- return methodInfo . MakeGenericMethod ( Enumerable . Repeat ( typeof ( object ) , methodInfo . GetGenericArguments ( ) . Length ) . ToArray ( ) ) ;
2907+ {
2908+ if ( inferedGenericsTypes != null && inferedGenericsTypes . Length == methodInfo . GetGenericArguments ( ) . Length )
2909+ {
2910+ return methodInfo . MakeGenericMethod ( inferedGenericsTypes ) ;
2911+ }
2912+ else
2913+ {
2914+ return methodInfo . MakeGenericMethod ( Enumerable . Repeat ( typeof ( object ) , methodInfo . GetGenericArguments ( ) . Length ) . ToArray ( ) ) ;
2915+ }
2916+ }
29002917 else
2918+ {
29012919 return methodInfo . MakeGenericMethod ( GetConcreteTypes ( genericsTypes ) ) ;
2920+ }
29022921 }
29032922
29042923 return methodInfo ;
@@ -3135,7 +3154,7 @@ protected virtual Type GetTypeByFriendlyName(string typeName, string genericType
31353154
31363155 if ( result == null )
31373156 {
3138- result = Types . ToList ( ) . Find ( type => type . Name . Equals ( typeName , StringComparisonForCasing ) ) ;
3157+ result = Types . ToList ( ) . Find ( type => type . Name . Equals ( typeName , StringComparisonForCasing ) || type . FullName . StartsWith ( typeName + "," ) ) ;
31393158 }
31403159
31413160 for ( int a = 0 ; a < Assemblies . Count && result == null ; a ++ )
0 commit comments