public void AssertAddBlock(StackBlockSpecBase <TInput, TState, TOperationEvent> block) { if (ContainsFinallyBlock()) { throw new OperationStackDeclarationException("No block can be added after a Finally block"); } }
/// <summary> /// Gets then next block spec to execute /// </summary> /// <param name="currentBlock">The current block</param> /// <param name="target">The next target</param> /// <returns></returns> private StackBlockSpecBase <TInput, TState, TOperationEvent> GetNext(StackBlockSpecBase <TInput, TState, TOperationEvent> currentBlock, BlockResultTarget target) { switch (target.FlowTarget) { case BlockFlowTarget.Return: return(blocks.GetNext(currentBlock.Index)); case BlockFlowTarget.Goto: return(blocks.GetByTagOrIndex(target.TargetTag, target.TargetIndex)); case BlockFlowTarget.Retry: return(currentBlock); case BlockFlowTarget.Reset: return(blocks.GetFirst()); case BlockFlowTarget.Restart: return(blocks.GetFirst()); case BlockFlowTarget.Skip: return(blocks.SkipBy(currentBlock.Index, target.TargetIndex)); case BlockFlowTarget.Complete: case BlockFlowTarget.Fail: return(blocks.GotoEnd(currentBlock.Index)); default: return(null); } }
public OperationStackExecutionState(OperationStackOptions options, StackBlocks <TInput, TState, TOperationEvent> blocks, TInput stackInput, TState initialState) { this.options = options; this.blocks = blocks; StackInput = stackInput; CurrentBlockSpec = blocks.GetFirst(); this.InitialState = initialState; State = initialState; }
/// <summary> /// Handle current block result and set next block to execute /// </summary> /// <param name="block">The execution block</param> /// <param name="blockResult">The execution block result</param> public void HandleBlockResultAndSetNext(StackBlockBase <TInput, TState, TOperationEvent> block, IBlockResult blockResult) { PreviousBlockSpec = CurrentBlockSpec; //Add to stack trace //Should we add trace to empty event blocks? To event blocks? StackTrace.Add(new BlockTraceResult <TOperationEvent>(block, blockResult)); //Handle Reset state in case of reset State = blockResult.Target.FlowTarget == BlockFlowTarget.Reset ? (blockResult.Target.ResetStateSet ? (TState)Convert.ChangeType(blockResult.Target.State, typeof(TState)) : default(TState)) : block.StackState; //Check fail state if (options.FailOnException && block.Events.HasUnhandledErrors) { IsFail = true; } //Override result is only applicable on Complete. Cache here in case of finally OverrideResult = blockResult.Target.OverrideResult; //Set next input NextInput = blockResult.GetNextInput(); //Get next block to execute CurrentBlockSpec = IsFail ? blocks.GotoEnd(CurrentBlockSpec.Index) : GetNext(CurrentBlockSpec, blockResult.Target); //If complete set overriden result if any if (CurrentBlockSpec == null && OverrideResult.HasValue) { //Set last result LastResult = OverrideResult; blockResult.OverrideResult(OverrideResult); } else { //Set last result LastResult = blockResult.Result; } }
public OperationStack <TInput, TState, TOperationEvent, TResult> CreateNew <TResult>(StackBlockSpecBase <TInput, TState, TOperationEvent> block) { Blocks.AssertAddBlock(block); return(new OperationStack <TInput, TState, TOperationEvent, TResult>(Blocks.Concat(block), Options, InitialStateBuilder, HasInput)); }
public IEnumerable <StackBlockSpecBase <TInput, TState, TOperationEvent> > Concat(StackBlockSpecBase <TInput, TState, TOperationEvent> block) => blocks.Concat(new[] { block });
public void Add(StackBlockSpecBase <TInput, TState, TOperationEvent> block) => blocks.Add(block);