5
5
using System . Linq . Dynamic . Core ;
6
6
using System . Linq . Expressions ;
7
7
using System . Reflection ;
8
+ using System . Text . RegularExpressions ;
8
9
using Newtonsoft . Json . Linq ;
9
10
using WorkflowCore . Interface ;
10
11
using WorkflowCore . Models ;
@@ -18,6 +19,40 @@ public class DefinitionLoader : IDefinitionLoader
18
19
{
19
20
private readonly IWorkflowRegistry _registry ;
20
21
private readonly ITypeResolver _typeResolver ;
22
+
23
+ // ParsingConfig to allow access to commonly used .NET methods like object.Equals
24
+ private static readonly ParsingConfig ParsingConfig = new ParsingConfig
25
+ {
26
+ AllowNewToEvaluateAnyType = true ,
27
+ AreContextKeywordsEnabled = true
28
+ } ;
29
+
30
+ // Transform expressions to be compatible with System.Linq.Dynamic.Core 1.6.0+
31
+ private static string TransformExpression ( string expression )
32
+ {
33
+ if ( string . IsNullOrEmpty ( expression ) )
34
+ return expression ;
35
+
36
+ // Transform object.Equals(a, b) to Convert.ToBoolean(a) == Convert.ToBoolean(b)
37
+ // This is a simple regex replacement for the common pattern
38
+ var objectEqualsPattern = @"object\.Equals\s*\(\s*([^,]+)\s*,\s*([^)]+)\s*\)" ;
39
+ var transformed = Regex . Replace ( expression , objectEqualsPattern ,
40
+ match =>
41
+ {
42
+ var arg1 = match . Groups [ 1 ] . Value . Trim ( ) ;
43
+ var arg2 = match . Groups [ 2 ] . Value . Trim ( ) ;
44
+
45
+ // If arg2 is a boolean literal, convert arg1 to boolean and compare
46
+ if ( arg2 == "true" || arg2 == "false" )
47
+ {
48
+ return $ "Convert.ToBoolean({ arg1 } ) == { arg2 } ";
49
+ }
50
+ // Otherwise, convert both to strings for comparison
51
+ return $ "Convert.ToString({ arg1 } ) == Convert.ToString({ arg2 } )";
52
+ } ) ;
53
+
54
+ return transformed ;
55
+ }
21
56
22
57
public DefinitionLoader ( IWorkflowRegistry registry , ITypeResolver typeResolver )
23
58
{
@@ -94,7 +129,7 @@ private WorkflowStepCollection ConvertSteps(ICollection<StepSourceV1> source, Ty
94
129
{
95
130
var cancelExprType = typeof ( Expression < > ) . MakeGenericType ( typeof ( Func < , > ) . MakeGenericType ( dataType , typeof ( bool ) ) ) ;
96
131
var dataParameter = Expression . Parameter ( dataType , "data" ) ;
97
- var cancelExpr = DynamicExpressionParser . ParseLambda ( new [ ] { dataParameter } , typeof ( bool ) , nextStep . CancelCondition ) ;
132
+ var cancelExpr = DynamicExpressionParser . ParseLambda ( ParsingConfig , false , new [ ] { dataParameter } , typeof ( bool ) , TransformExpression ( nextStep . CancelCondition ) ) ;
98
133
targetStep . CancelCondition = cancelExpr ;
99
134
}
100
135
@@ -217,7 +252,7 @@ private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, Wo
217
252
foreach ( var output in source . Outputs )
218
253
{
219
254
var stepParameter = Expression . Parameter ( stepType , "step" ) ;
220
- var sourceExpr = DynamicExpressionParser . ParseLambda ( new [ ] { stepParameter } , typeof ( object ) , output . Value ) ;
255
+ var sourceExpr = DynamicExpressionParser . ParseLambda ( ParsingConfig , false , new [ ] { stepParameter } , typeof ( object ) , TransformExpression ( output . Value ) ) ;
221
256
222
257
var dataParameter = Expression . Parameter ( dataType , "data" ) ;
223
258
@@ -344,7 +379,7 @@ private void AttachOutcomes(StepSourceV1 source, Type dataType, WorkflowStep ste
344
379
345
380
foreach ( var nextStep in source . SelectNextStep )
346
381
{
347
- var sourceDelegate = DynamicExpressionParser . ParseLambda ( new [ ] { dataParameter , outcomeParameter } , typeof ( object ) , nextStep . Value ) . Compile ( ) ;
382
+ var sourceDelegate = DynamicExpressionParser . ParseLambda ( ParsingConfig , false , new [ ] { dataParameter , outcomeParameter } , typeof ( object ) , TransformExpression ( nextStep . Value ) ) . Compile ( ) ;
348
383
Expression < Func < object , object , bool > > sourceExpr = ( data , outcome ) => System . Convert . ToBoolean ( sourceDelegate . DynamicInvoke ( data , outcome ) ) ;
349
384
step . Outcomes . Add ( new ExpressionOutcome < object > ( sourceExpr )
350
385
{
@@ -361,7 +396,7 @@ private Type FindType(string name)
361
396
private static Action < IStepBody , object , IStepExecutionContext > BuildScalarInputAction ( KeyValuePair < string , object > input , ParameterExpression dataParameter , ParameterExpression contextParameter , ParameterExpression environmentVarsParameter , PropertyInfo stepProperty )
362
397
{
363
398
var expr = System . Convert . ToString ( input . Value ) ;
364
- var sourceExpr = DynamicExpressionParser . ParseLambda ( new [ ] { dataParameter , contextParameter , environmentVarsParameter } , typeof ( object ) , expr ) ;
399
+ var sourceExpr = DynamicExpressionParser . ParseLambda ( ParsingConfig , false , new [ ] { dataParameter , contextParameter , environmentVarsParameter } , typeof ( object ) , TransformExpression ( expr ) ) ;
365
400
366
401
void acn ( IStepBody pStep , object pData , IStepExecutionContext pContext )
367
402
{
@@ -394,7 +429,7 @@ void acn(IStepBody pStep, object pData, IStepExecutionContext pContext)
394
429
{
395
430
if ( prop . Name . StartsWith ( "@" ) )
396
431
{
397
- var sourceExpr = DynamicExpressionParser . ParseLambda ( new [ ] { dataParameter , contextParameter , environmentVarsParameter } , typeof ( object ) , prop . Value . ToString ( ) ) ;
432
+ var sourceExpr = DynamicExpressionParser . ParseLambda ( ParsingConfig , false , new [ ] { dataParameter , contextParameter , environmentVarsParameter } , typeof ( object ) , TransformExpression ( prop . Value . ToString ( ) ) ) ;
398
433
object resolvedValue = sourceExpr . Compile ( ) . DynamicInvoke ( pData , pContext , Environment . GetEnvironmentVariables ( ) ) ;
399
434
subobj . Remove ( prop . Name ) ;
400
435
subobj . Add ( prop . Name . TrimStart ( '@' ) , JToken . FromObject ( resolvedValue ) ) ;
0 commit comments