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); }
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); } } }
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); }
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); }
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); }
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); }
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); }
private static void SetFlowResponseProperty(TFlowResponse flowResponse, FlowObjectProperty flowResponseProperty, FlowValues flowValues) { if (flowValues.TryGetValue(flowResponseProperty.PropertyInfo.Name, out var flowValue)) { flowResponseProperty.PropertyInfo.SetValue(flowResponse, flowValue); } }
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); }
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); } } }
protected virtual void OnDebugEvent(string stepName, FlowDebugEvent debugEvent, FlowValues flowValues) { }