protected virtual void BuildWorkflow(IEnumerable <WorkflowNode> allNodes, DefinitionSourceV1 source, IEnumerable <AbpWorkflowStepBody> stepBodys, WorkflowNode node) { if (source.Steps.Any(u => u.Id == node.Key)) { return; } var stepSource = new StepSourceV1(); stepSource.Id = node.Key; stepSource.Name = node.Key; AbpWorkflowStepBody stepbody = stepBodys.FirstOrDefault(u => u.Name == node.StepBody.Name); if (stepbody == null) { stepbody = new AbpWorkflowStepBody() { StepBodyType = typeof(NullStepBody) }; } stepSource.StepType = $"{stepbody.StepBodyType.FullName}, {stepbody.StepBodyType.Assembly.FullName}"; foreach (var input in stepbody.Inputs) { var value = node.StepBody.Inputs[input.Key].Value; if (!(value is IDictionary <string, object> || value is IDictionary <object, object>)) { value = $"\"{value}\""; } stepSource.Inputs.TryAdd(input.Key, value); } source.Steps.Add(stepSource); BuildBranching(allNodes, source, stepSource, stepBodys, node.NextNodes); }
private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step) { foreach (var output in source.Outputs) { var stepParameter = Expression.Parameter(stepType, "step"); var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { stepParameter }, typeof(object), output.Value); var dataParameter = Expression.Parameter(dataType, "data"); Expression targetProperty; // Check if our datatype has a matching property var propertyInfo = dataType.GetProperty(output.Key); if (propertyInfo != null) { targetProperty = Expression.Property(dataParameter, propertyInfo); } else { // If we did not find a matching property try to find a Indexer with string parameter propertyInfo = dataType.GetProperty("Item"); targetProperty = Expression.Property(dataParameter, propertyInfo, Expression.Constant(output.Key)); } var targetExpr = Expression.Lambda(targetProperty, dataParameter); step.Outputs.Add(new DataMapping { Source = sourceExpr, Target = targetExpr }); } }
private void AttachInputs(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step) { foreach (var input in source.Inputs) { var dataParameter = Expression.Parameter(dataType, "data"); var contextParameter = Expression.Parameter(typeof(IStepExecutionContext), "context"); var environmentVarsParameter = Expression.Parameter(typeof(IDictionary), "environment"); var stepProperty = stepType.GetProperty(input.Key); if (stepProperty == null) { throw new ArgumentException($"Unknown property for input {input.Key} on {source.Id}"); } if (input.Value is string) { var acn = BuildScalarInputAction(input, dataParameter, contextParameter, environmentVarsParameter, stepProperty); step.Inputs.Add(new ActionParameter <IStepBody, object>(acn)); continue; } if ((input.Value is IDictionary <string, object>) || (input.Value is IDictionary <object, object>)) { var acn = BuildObjectInputAction(input, dataParameter, contextParameter, environmentVarsParameter, stepProperty); step.Inputs.Add(new ActionParameter <IStepBody, object>(acn)); continue; } throw new ArgumentException($"Unknown type for input {input.Key} on {source.Id}"); } }
private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step) { foreach (var output in source.Outputs) { var stepParameter = Expression.Parameter(stepType, "step"); var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { stepParameter }, typeof(object), output.Value); var dataParameter = Expression.Parameter(dataType, "data"); Expression targetProperty; // Check if our datatype has a matching property var propertyInfo = dataType.GetProperty(output.Key); if (propertyInfo != null) { targetProperty = Expression.Property(dataParameter, propertyInfo); var targetExpr = Expression.Lambda(targetProperty, dataParameter); step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); } else { // If we did not find a matching property try to find a Indexer with string parameter propertyInfo = dataType.GetProperty("Item"); targetProperty = Expression.Property(dataParameter, propertyInfo, Expression.Constant(output.Key)); Action <IStepBody, object> acn = (pStep, pData) => { object resolvedValue = sourceExpr.Compile().DynamicInvoke(pStep);; propertyInfo.SetValue(pData, resolvedValue, new object[] { output.Key }); }; step.Outputs.Add(new ActionParameter <IStepBody, object>(acn)); } } }
private void AttachStatics(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step) { foreach (var staticMap in source.Statics) { var targetExpr = Expression.Property(Expression.Parameter(stepType), staticMap.Key); step.Statics.Add(new DataMappingStatics() { Source = staticMap.Value, Target = Expression.Lambda(targetExpr) }); } }
private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step) { foreach (var output in source.Outputs) { var stepParameter = Expression.Parameter(stepType, "step"); var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { stepParameter }, typeof(object), output.Value); var targetExpr = Expression.Property(Expression.Parameter(dataType), output.Key); step.Outputs.Add(new DataMapping() { Source = sourceExpr, Target = Expression.Lambda(targetExpr) }); } }
private void AttachInputs(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step) { foreach (var input in source.Inputs) { var dataParameter = Expression.Parameter(dataType, "data"); var contextParameter = Expression.Parameter(typeof(IStepExecutionContext), "context"); var sourceExpr = DynamicExpressionParser.ParseLambda(new [] { dataParameter, contextParameter }, typeof(object), input.Value); var stepParameter = Expression.Parameter(stepType, "step"); var targetProperty = Expression.Property(stepParameter, input.Key); var targetExpr = Expression.Lambda(targetProperty, stepParameter); step.Inputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); } }
private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step) { foreach (var output in source.Outputs) { var stepParameter = Expression.Parameter(stepType, "step"); var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { stepParameter }, typeof(object), output.Value); var dataParameter = Expression.Parameter(dataType, "data"); if (output.Key.Contains(".") || output.Key.Contains("[")) { AttachNestedOutput(output, step, source, sourceExpr, dataParameter); } else { AttachDirectlyOutput(output, step, dataType, sourceExpr, dataParameter); } } }
private void AttachOutcomes(StepSourceV1 source, Type dataType, WorkflowStep step) { if (!string.IsNullOrEmpty(source.NextStepId)) { step.Outcomes.Add(new StepOutcome() { ExternalNextStepId = $"{source.NextStepId}" }); } foreach (var nextStep in source.OutcomeSteps) { var dataParameter = Expression.Parameter(dataType, "data"); var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { dataParameter }, typeof(object), nextStep.Value); step.Outcomes.Add(new StepOutcome() { Value = sourceExpr, ExternalNextStepId = $"{nextStep.Key}" }); } }
private void AttachOutcomes(StepSourceV1 source, Type dataType, WorkflowStep step) { if (!string.IsNullOrEmpty(source.NextStepId)) { step.Outcomes.Add(new ValueOutcome { ExternalNextStepId = $"{source.NextStepId}" }); } var dataParameter = Expression.Parameter(dataType, "data"); var outcomeParameter = Expression.Parameter(typeof(object), "outcome"); foreach (var nextStep in source.SelectNextStep) { var sourceDelegate = DynamicExpressionParser.ParseLambda(new[] { dataParameter, outcomeParameter }, typeof(object), nextStep.Value).Compile(); Expression <Func <object, object, bool> > sourceExpr = (data, outcome) => System.Convert.ToBoolean(sourceDelegate.DynamicInvoke(data, outcome)); step.Outcomes.Add(new ExpressionOutcome <object>(sourceExpr) { ExternalNextStepId = $"{nextStep.Key}" }); } }
private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step) { foreach (var output in source.Outputs) { var stepParameter = Expression.Parameter(stepType, "step"); var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { stepParameter }, typeof(object), output.Value); var dataParameter = Expression.Parameter(dataType, "data"); Expression targetProperty; // If the property has a point, check for a nested type Expression parentExpression = dataParameter; Type parentDataType = dataType; string key = output.Key; bool continueLoop = key.Contains("."); while (continueLoop) { var indexOfPoint = key.IndexOf(".", StringComparison.InvariantCultureIgnoreCase); var subPropertyName = key.Substring(0, indexOfPoint); var subProperty = parentDataType.GetProperty(subPropertyName); key = key.Substring(indexOfPoint + 1); continueLoop = key.Contains("."); var subPropertyParameterProperty = Expression.Property(parentExpression, subProperty); parentExpression = subPropertyParameterProperty; parentDataType = subProperty.PropertyType; if (!continueLoop) { subPropertyName = key; subProperty = parentDataType.GetProperty(subPropertyName); subPropertyParameterProperty = Expression.Property(parentExpression, subProperty); var subPropertyTarget = Expression.Lambda(subPropertyParameterProperty, dataParameter); step.Outputs.Add(new MemberMapParameter(sourceExpr, subPropertyTarget)); return; } } // Check if our datatype has a matching property var propertyInfo = dataType.GetProperty(output.Key); if (propertyInfo != null) { targetProperty = Expression.Property(dataParameter, propertyInfo); var targetExpr = Expression.Lambda(targetProperty, dataParameter); step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); } else { // If we did not find a matching property try to find a Indexer with string parameter propertyInfo = dataType.GetProperty("Item"); targetProperty = Expression.Property(dataParameter, propertyInfo, Expression.Constant(output.Key)); Action <IStepBody, object> acn = (pStep, pData) => { object resolvedValue = sourceExpr.Compile().DynamicInvoke(pStep);; propertyInfo.SetValue(pData, resolvedValue, new object[] { output.Key }); }; step.Outputs.Add(new ActionParameter <IStepBody, object>(acn)); } } }
private void AttachNestedOutput(KeyValuePair <string, string> output, WorkflowStep step, StepSourceV1 source, LambdaExpression sourceExpr, ParameterExpression dataParameter) { PropertyInfo propertyInfo = null; String[] paths = output.Key.Split('.'); Expression targetProperty = dataParameter; bool hasAddOutput = false; foreach (String propertyName in paths) { if (hasAddOutput) { throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); } if (targetProperty == null) { break; } if (propertyName.Contains("[")) { String[] items = propertyName.Split('['); if (items.Length != 2) { throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); } items[1] = items[1].Trim().TrimEnd(']').Trim().Trim('"'); MemberExpression memberExpression = Expression.Property(targetProperty, items[0]); if (memberExpression == null) { throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}"); } propertyInfo = ((PropertyInfo)memberExpression.Member).PropertyType.GetProperty("Item"); Action <IStepBody, object> acn = (pStep, pData) => { var targetExpr = Expression.Lambda(memberExpression, dataParameter); object data = targetExpr.Compile().DynamicInvoke(pData); object resolvedValue = sourceExpr.Compile().DynamicInvoke(pStep);; propertyInfo.SetValue(data, resolvedValue, new object[] { items[1] }); }; step.Outputs.Add(new ActionParameter <IStepBody, object>(acn)); hasAddOutput = true; } else { try { targetProperty = Expression.Property(targetProperty, propertyName); } catch { targetProperty = null; break; } } } if (targetProperty != null && !hasAddOutput) { var targetExpr = Expression.Lambda(targetProperty, dataParameter); step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr)); } }
protected virtual void BuildBranching(IEnumerable <WorkflowNode> allNodes, DefinitionSourceV1 source, StepSourceV1 stepSource, IEnumerable <AbpWorkflowStepBody> stepBodys, IEnumerable <WorkflowConditionNode> nodes) { foreach (var nextNode in nodes) { var node = allNodes.First(u => u.Key == nextNode.NodeId); stepSource.SelectNextStep[nextNode.NodeId] = "1==1"; if (nextNode.Conditions.Count() > 0) { List <string> exps = new List <string>(); foreach (var cond in nextNode.Conditions) { if (cond.Value is string && (!decimal.TryParse(cond.Value.ToString(), out decimal tempValue))) { if (cond.Operator != "==" && cond.Operator != "!=") { throw new AbpException($" if {cond.Field} is type of 'String', the Operator must be \"==\" or \"!=\""); } exps.Add($"data[\"{cond.Field}\"].ToString() {cond.Operator} \"{cond.Value}\""); continue; } exps.Add($"decimal.Parse(data[\"{cond.Field}\"].ToString()) {cond.Operator} {cond.Value}"); } stepSource.SelectNextStep[nextNode.NodeId] = string.Join(" && ", exps); } BuildWorkflow(allNodes, source, stepBodys, node); } }