1
1
/******************************************************************************************************
2
2
Title : ExpressionEvaluator (https://github.com/codingseb/ExpressionEvaluator)
3
- Version : 1.4.1 .0
3
+ Version : 1.4.2 .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
@@ -452,11 +452,18 @@ public static void ClearAllCaches()
452
452
453
453
#region Assemblies, Namespaces and types lists
454
454
455
+ private static IList < Assembly > staticAssemblies ;
456
+ private IList < Assembly > assemblies ;
457
+
455
458
/// <summary>
456
459
/// All assemblies needed to resolves Types
457
460
/// by default all Assemblies loaded in the current AppDomain
458
461
/// </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
+ }
460
467
461
468
/// <summary>
462
469
/// All Namespaces Where to find types
@@ -848,8 +855,6 @@ public IDictionary<string, object> Variables
848
855
/// </summary>
849
856
public ExpressionEvaluator ( )
850
857
{
851
- AssembliesInit ( ) ;
852
-
853
858
DefaultDecimalSeparatorInit ( ) ;
854
859
855
860
Init ( ) ;
@@ -864,11 +869,6 @@ public ExpressionEvaluator(IDictionary<string, object> variables) : this()
864
869
Variables = variables ;
865
870
}
866
871
867
- protected virtual void AssembliesInit ( )
868
- {
869
- Assemblies = AppDomain . CurrentDomain . GetAssemblies ( ) . ToList ( ) ;
870
- }
871
-
872
872
protected virtual void DefaultDecimalSeparatorInit ( )
873
873
{
874
874
numberRegexPattern = string . Format ( numberRegexOrigPattern , @"\." , string . Empty ) ;
@@ -1362,8 +1362,6 @@ void forAction(int index)
1362
1362
breakCalled = isBreak ;
1363
1363
continueCalled = isContinue ;
1364
1364
1365
- inScript = false ;
1366
-
1367
1365
if ( isReturn || OptionOnNoReturnKeywordFoundInScriptAction == OptionOnNoReturnKeywordFoundInScriptAction . ReturnAutomaticallyLastEvaluatedExpression )
1368
1366
return lastResult ;
1369
1367
else if ( OptionOnNoReturnKeywordFoundInScriptAction == OptionOnNoReturnKeywordFoundInScriptAction . ReturnNull )
@@ -1419,7 +1417,7 @@ public object Evaluate(string expression)
1419
1417
1420
1418
for ( int i = 0 ; i < expression . Length ; i ++ )
1421
1419
{
1422
- if ( ! ParsingMethods . Any ( m => m ( expression , stack , ref i ) ) )
1420
+ if ( ! ParsingMethods . Any ( parsingMethod => parsingMethod ( expression , stack , ref i ) ) )
1423
1421
{
1424
1422
string s = expression . Substring ( i , 1 ) ;
1425
1423
@@ -1735,6 +1733,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
1735
1733
object obj = stack . Pop ( ) ;
1736
1734
object keepObj = obj ;
1737
1735
Type objType = null ;
1736
+ Type [ ] inferedGenericsTypes = obj . GetType ( ) . GenericTypeArguments ;
1738
1737
ValueTypeNestingTrace valueTypeNestingTrace = null ;
1739
1738
1740
1739
if ( obj != null && TypesToBlock . Contains ( obj . GetType ( ) ) )
@@ -1775,7 +1774,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
1775
1774
throw new ExpressionEvaluatorSyntaxErrorException ( $ "[{ objType } ] object has no Method named \" { varFuncName } \" .") ;
1776
1775
1777
1776
// 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 ) ;
1779
1778
1780
1779
// if not found check if obj is an expandoObject or similar
1781
1780
if ( obj is IDynamicMetaObjectProvider
@@ -1807,7 +1806,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
1807
1806
for ( int e = 0 ; e < StaticTypesForExtensionsMethods . Count && methodInfo == null ; e ++ )
1808
1807
{
1809
1808
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 ) ;
1811
1810
isExtention = methodInfo != null ;
1812
1811
}
1813
1812
}
@@ -2042,17 +2041,14 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
2042
2041
{
2043
2042
dictionaryObject [ varFuncName ] = varValue ;
2044
2043
}
2044
+ else if ( valueTypeNestingTrace != null )
2045
+ {
2046
+ valueTypeNestingTrace . Value = varValue ;
2047
+ valueTypeNestingTrace . AssignValue ( ) ;
2048
+ }
2045
2049
else
2046
2050
{
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 ) ;
2056
2052
}
2057
2053
}
2058
2054
}
@@ -2756,21 +2752,33 @@ protected virtual bool GetLambdaExpression(string expression, Stack<object> stac
2756
2752
2757
2753
stack . Push ( new InternalDelegate ( ( object [ ] args ) =>
2758
2754
{
2759
- Dictionary < string , object > vars = new Dictionary < string , object > ( Variables ) ;
2755
+ var vars = new Dictionary < string , object > ( variables ) ;
2760
2756
2761
2757
for ( int a = 0 ; a < argsNames . Count || a < args . Length ; a ++ )
2762
2758
{
2763
2759
vars [ argsNames [ a ] ] = args [ a ] ;
2764
2760
}
2765
2761
2766
- ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator ( vars ) ;
2762
+ var savedVars = variables ;
2763
+ Variables = vars ;
2767
2764
2768
2765
string lambdaBody = lambdaExpressionMatch . Groups [ "expression" ] . Value . Trim ( ) ;
2769
2766
2767
+ object result = null ;
2768
+
2770
2769
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
+ }
2772
2774
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 ;
2774
2782
} ) ) ;
2775
2783
2776
2784
return true ;
@@ -2781,7 +2789,7 @@ protected virtual bool GetLambdaExpression(string expression, Stack<object> stac
2781
2789
}
2782
2790
}
2783
2791
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 )
2785
2793
{
2786
2794
MethodInfo methodInfo = null ;
2787
2795
List < object > modifiedArgs = new List < object > ( args ) ;
@@ -2790,7 +2798,7 @@ protected virtual MethodInfo GetRealMethod(ref Type type, ref object obj, string
2790
2798
&& ( func . StartsWith ( "Fluid" , StringComparisonForCasing )
2791
2799
|| func . StartsWith ( "Fluent" , StringComparisonForCasing ) ) )
2792
2800
{
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 ) ;
2794
2802
if ( methodInfo != null )
2795
2803
{
2796
2804
if ( methodInfo . ReturnType == typeof ( void ) )
@@ -2818,7 +2826,7 @@ protected virtual MethodInfo GetRealMethod(ref Type type, ref object obj, string
2818
2826
2819
2827
if ( methodInfo != null )
2820
2828
{
2821
- methodInfo = MakeConcreteMethodIfGeneric ( methodInfo , genericsTypes ) ;
2829
+ methodInfo = MakeConcreteMethodIfGeneric ( methodInfo , genericsTypes , inferedGenericsTypes ) ;
2822
2830
}
2823
2831
else
2824
2832
{
@@ -2828,7 +2836,7 @@ protected virtual MethodInfo GetRealMethod(ref Type type, ref object obj, string
2828
2836
2829
2837
for ( int m = 0 ; m < methodInfos . Count && methodInfo == null ; m ++ )
2830
2838
{
2831
- methodInfos [ m ] = MakeConcreteMethodIfGeneric ( methodInfos [ m ] , genericsTypes ) ;
2839
+ methodInfos [ m ] = MakeConcreteMethodIfGeneric ( methodInfos [ m ] , genericsTypes , inferedGenericsTypes ) ;
2832
2840
2833
2841
bool parametersCastOK = true ;
2834
2842
@@ -2891,14 +2899,25 @@ protected virtual MethodInfo GetRealMethod(ref Type type, ref object obj, string
2891
2899
return methodInfo ;
2892
2900
}
2893
2901
2894
- protected virtual MethodInfo MakeConcreteMethodIfGeneric ( MethodInfo methodInfo , string genericsTypes = "" )
2902
+ protected virtual MethodInfo MakeConcreteMethodIfGeneric ( MethodInfo methodInfo , string genericsTypes , Type [ ] inferedGenericsTypes )
2895
2903
{
2896
2904
if ( methodInfo . IsGenericMethod )
2897
2905
{
2898
2906
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
+ }
2900
2917
else
2918
+ {
2901
2919
return methodInfo . MakeGenericMethod ( GetConcreteTypes ( genericsTypes ) ) ;
2920
+ }
2902
2921
}
2903
2922
2904
2923
return methodInfo ;
@@ -3135,7 +3154,7 @@ protected virtual Type GetTypeByFriendlyName(string typeName, string genericType
3135
3154
3136
3155
if ( result == null )
3137
3156
{
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 + "," ) ) ;
3139
3158
}
3140
3159
3141
3160
for ( int a = 0 ; a < Assemblies . Count && result == null ; a ++ )
0 commit comments