示例#1
0
        private async Task DoActivity(ActivityFlowStep activityFlowStep, FlowContext stepFlowContext,
                                      FlowValues flowValues, FlowTrace flowTrace, CancellationToken cancellationToken)
        {
            var activityRequest = CreateRequest(stepFlowContext, activityFlowStep, flowValues);

            if (IsRequestDisabled(activityRequest))
            {
                _logger?.LogActivityRequestDisabled(stepFlowContext, activityRequest);
                return;
            }

            _logger?.LogActivityRequest(stepFlowContext, activityRequest);

            var stopWatch = new Stopwatch();

            stopWatch.Start();

            object activityResponse =
                await GetActivityResponse(
                    stepFlowContext, activityFlowStep, activityRequest, cancellationToken);

            stopWatch.Stop();

            ValidateFlowObjectValues(activityResponse, activityResponse.GetType().GetFlowObjectType(), activityFlowStep.Name);

            flowTrace.AddStep(new FlowTraceStep {
                StepType = FlowTraceStepType.Activity, Name = activityFlowStep.Name
            });

            _logger?.LogActivityResponse(stepFlowContext, activityResponse, stopWatch.ElapsedMilliseconds);

            SetFlowValuesFromResponse(activityFlowStep.Definition, stepFlowContext, flowValues, activityRequest, activityResponse);

            AppendResponseFlowTrace(flowTrace, activityResponse);
        }
示例#2
0
        private static void PopulateRequestBoundValues(IFlowStepRequest request, FlowObjectType requestType, FlowStep flowStep,
                                                       FlowValues flowValues, ISet <string> setPropertyNames)
        {
            var boundProperties = requestType.Properties.Where(p => !setPropertyNames.Contains(p.Name));

            foreach (var boundProperty in boundProperties)
            {
                var inputBinding = flowStep.Definition.GetInputBinding(boundProperty);

                if (inputBinding.TryGetRequestValue(flowValues, request, out var requestValue))
                {
                    boundProperty.PropertyInfo.SetValue(request, requestValue);
                }
            }
        }
示例#3
0
        private int CheckDecision(int flowStepIndex, DecisionFlowStepBase decisionFlowStep, FlowDefinition <TFlowRequest, TFlowResponse> flowDefinition,
                                  FlowContext stepFlowContext, FlowValues flowValues, FlowTrace flowTrace)
        {
            var decisionRequest = (FlowDecisionBase)CreateRequest(stepFlowContext, decisionFlowStep, flowValues);

            // TODO: Pass the targets directly into GetMatchingBranchIndex
            decisionFlowStep.Branches.ForEach(b => decisionRequest.AddBranch(b.Targets));

            _logger?.LogDecisionRequest(stepFlowContext, decisionRequest);

            var branchIndex = decisionRequest.GetMatchingBranchIndex();

            if (branchIndex < 0 || branchIndex >= decisionFlowStep.Branches.Count)
            {
                throw new FlowException($"The branch index returned was out of bounds of the branch array: {branchIndex}");
            }

            var branch = decisionFlowStep.Branches[branchIndex];

            flowTrace.AddStep(new FlowTraceStep
            {
                StepType = FlowTraceStepType.Decision, Name = decisionFlowStep.Name, BranchTargets = branch.Targets
            });

            _logger?.LogDecisionResponse(stepFlowContext, branch);

            if (branch.IsEnd)
            {
                return(int.MaxValue);
            }

            if (branch.IsUnhandled)
            {
                throw new FlowUnhandledElseException($"Unhandled ELSE for decision '{decisionFlowStep.Name}'");
            }

            var isContinue = (branch.NextStepName == null);

            if (isContinue)
            {
                return(flowStepIndex + 1);
            }

            var nextFlowStepIndex = flowDefinition.GetStepIndex(branch.NextStepName);

            return(nextFlowStepIndex);
        }
示例#4
0
        private static TFlowResponse BuildFlowResponse(FlowContext flowContext, FlowDefinition <TFlowRequest, TFlowResponse> flowDefinition,
                                                       FlowTrace flowTrace, FlowValues flowValues)
        {
            var flowResponseType = typeof(TFlowResponse);
            var flowResponse     = (TFlowResponse)Activator.CreateInstance(flowResponseType);
            var flowObjectType   = flowResponseType.GetFlowObjectType();

            var missingMandatoryPropertyNames = new List <string>();

            foreach (var flowObjectProperty in flowObjectType.Properties)
            {
                var binding =
                    flowDefinition.Finalizer?.Inputs.Find(b => b.Property.Name == flowObjectProperty.Name)
                    ?? new FlowValueInputBinding(flowObjectProperty)
                {
                    FlowValueSelector = new FlowValueSingleSelector(flowObjectProperty.Name)
                };

                if (binding.TryGetRequestValue(flowValues, flowResponse, out var responseValue))
                {
                    flowObjectProperty.PropertyInfo.SetValue(flowResponse, responseValue);
                }

                CheckMandatoryFlowObjectProperty(flowResponse, flowObjectProperty, missingMandatoryPropertyNames);
            }

            if (missingMandatoryPropertyNames.Count > 0)
            {
                throw new FlowException(
                          $"The following mandatory properties were not populated on {flowResponseType.FullName}: " +
                          $"{string.Join(", ", missingMandatoryPropertyNames.ToArray())}");
            }

            if (flowResponse is FlowResponse baseFlowResponse)
            {
                baseFlowResponse.CorrelationId  = flowContext.CorrelationId;
                baseFlowResponse.RequestId      = flowContext.RequestId;
                baseFlowResponse.FlowInstanceId = flowContext.FlowInstanceId;
                baseFlowResponse.Trace          = flowTrace;
            }

            return(flowResponse);
        }
示例#5
0
        private async Task <int> PerformFlowStep(FlowContext stepFlowContext, FlowDefinition <TFlowRequest, TFlowResponse> flowDefinition, FlowStep flowStep,
                                                 int flowStepIndex, FlowValues flowValues, FlowTrace flowTrace, CancellationToken cancellationToken)
        {
            int nextFlowStepIndex;

            switch (flowStep)
            {
            case ActivityFlowStep activityFlowStep:
                await DoActivity(
                    activityFlowStep, stepFlowContext, flowValues,
                    flowTrace, cancellationToken);

                nextFlowStepIndex = flowStepIndex + 1;
                break;

            case DecisionFlowStepBase decisionFlowStep:
                nextFlowStepIndex =
                    CheckDecision(
                        flowStepIndex, decisionFlowStep, flowDefinition, stepFlowContext, flowValues,
                        flowTrace);
                break;

            case GotoFlowStep gotoFlowStep:
                _logger.LogGoto(stepFlowContext, gotoFlowStep.NextStepName);
                nextFlowStepIndex = flowDefinition.GetStepIndex(gotoFlowStep.NextStepName);
                break;

            case LabelFlowStep _:
                RecordLabelStep(flowTrace, stepFlowContext);
                nextFlowStepIndex = flowStepIndex + 1;
                break;

            case EndFlowStep _:
                nextFlowStepIndex = int.MaxValue;
                break;

            default:
                throw new FlowException(
                          $"Unexpected flow activityFlowStep type {flowStep.GetType().FullName}");
            }

            return(nextFlowStepIndex);
        }
示例#6
0
        private static FlowValues GetInitialFlowValues(FlowDefinition <TFlowRequest, TFlowResponse> flowDefinition,
                                                       TFlowRequest flowRequest)
        {
            var flowValues = new FlowValues();

            var flowRequestType       = typeof(TFlowRequest);
            var flowRequestProperties = flowRequestType.GetFlowObjectType();

            var missingMandatoryPropertyNames = new List <string>();

            foreach (var flowRequestProperty in flowRequestProperties.Properties)
            {
                var binding = flowDefinition.Initializer?.Outputs.Find(b => b.Property.Name == flowRequestProperty.Name);

                var requestValue = flowRequestProperty.PropertyInfo.GetValue(flowRequest);

                if (binding == null)
                {
                    flowValues.SetValue(flowRequestProperty.Name, requestValue);
                }
                else
                {
                    var outputValues = binding.GetOutputValues(requestValue, flowRequest);

                    foreach (var outputValueName in outputValues.Keys)
                    {
                        flowValues.SetValue(outputValueName, outputValues[outputValueName]);
                    }
                }

                CheckMandatoryFlowObjectProperty(flowRequest, flowRequestProperty, missingMandatoryPropertyNames);
            }

            if (missingMandatoryPropertyNames.Count > 0)
            {
                throw new FlowException(
                          $"The following mandatory properties were not populated on {flowRequestType.FullName}: " +
                          $"{string.Join(", ", missingMandatoryPropertyNames.ToArray())}");
            }

            return(flowValues);
        }
示例#7
0
        internal bool TryGetRequestValue(FlowValues flowValues, object request, out object requestValue)
        {
            requestValue = (object)null;

            var flowValueNames = this.FlowValueSelector.ResolveNames(request, flowValues);

            if (this.Property.IsDictionaryBinding)
            {
                var flowValueDictionary = (IFlowValueDictionary)Activator.CreateInstance(this.Property.DictionaryType);

                foreach (var flowValueName in flowValueNames)
                {
                    if (!flowValues.TryGetValue(flowValueName, out var flowValue))
                    {
                        continue;
                    }

                    var value = GetMappedValue(flowValue);
                    var name  = GetMappedName(flowValueName, request);

                    flowValueDictionary.SetValue(name, value);
                }

                requestValue = flowValueDictionary;
            }
            else
            {
                var flowValueName = flowValueNames.First();

                if (flowValues.TryGetValue(flowValueName, out var flowValue))
                {
                    requestValue = GetMappedValue(flowValue);
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
示例#8
0
 private static void SetFlowResponseProperty(TFlowResponse flowResponse,
                                             FlowObjectProperty flowResponseProperty, FlowValues flowValues)
 {
     if (flowValues.TryGetValue(flowResponseProperty.PropertyInfo.Name, out var flowValue))
     {
         flowResponseProperty.PropertyInfo.SetValue(flowResponse, flowValue);
     }
 }
示例#9
0
        private IFlowStepRequest CreateRequest(FlowContext flowContext, FlowStep flowStep, FlowValues flowValues)
        {
            var request = (IFlowStepRequest)Activator.CreateInstance(flowStep.Definition.RequestType);

            request.FlowContext = flowContext;

            var requestType = request.GetType().GetFlowObjectType();

            var setPropertyNames = PopulateRequestSetValues(flowStep, request);

            PopulateRequestBoundValues(request, requestType, flowStep, flowValues, setPropertyNames);

            PopulateRequestOverriddenValues(flowContext, request, requestType, flowStep);

            ValidateFlowObjectValues(request, requestType, flowStep.Name);

            return(request);
        }
示例#10
0
        private void SetFlowValuesFromResponse(FlowStepDefinition flowStepDefinition, FlowContext flowContext, FlowValues flowValues,
                                               object request, object response)
        {
            var responseFlowObjectType = response.GetType().GetFlowObjectType();

            var bindingSummaries = new List <Tuple <string, string> >();

            foreach (var flowObjectProperty in responseFlowObjectType.Properties)
            {
                var responsePropertyValue = flowObjectProperty.PropertyInfo.GetValue(response);

                var outputBinding = flowStepDefinition.GetOutputBinding(flowObjectProperty);

                var outputValues = outputBinding.GetOutputValues(responsePropertyValue, request);

                foreach (var outputValue in outputValues)
                {
                    flowValues.SetValue(outputValue.Key, outputValue.Value);
                }
            }
        }
示例#11
0
 protected virtual void OnDebugEvent(string stepName, FlowDebugEvent debugEvent, FlowValues flowValues)
 {
 }