/// <summary> /// The item to add to the current collection. /// Add the specified state. /// </summary> /// <param name="state">State.</param> public void Add(WorkflowState <T, TContext> state) { Add(state.Id, state); }
/// <summary> /// Initializes a new instance of the <see cref="Autoflow.WorkflowEngine{T,TContext}"/> class. /// </summary> /// <param name="workflowDefinition"></param> /// <param name="currentState"></param> /// <param name="workflowContext"></param> public WorkflowEngine(WorkflowDefinition <T, TContext> workflowDefinition, WorkflowState <T, TContext> currentState, TContext workflowContext) { Guard.ArgumentIsNotNull(workflowDefinition, nameof(workflowDefinition)); _onTransitionedEvent = new OnWorkflowTransitionedEvent <T, TContext>(); _workflowContext = workflowContext; _workflowDefinition = workflowDefinition; CurrentState = currentState ?? workflowDefinition.Transitions.First().FromState; _stateMachine = new StateMachine <WorkflowState <T, TContext>, WorkflowTrigger <T> >(() => CurrentState, s => CurrentState = s); // Get a distinct list of states with a trigger from state configuration // "State => Trigger => TargetState var states = workflowDefinition.Transitions.AsQueryable() .Select(x => x.FromState) .Distinct() .Select(x => x) .ToList(); // Assign triggers to states foreach (var state in states) { var triggers = workflowDefinition.Transitions.AsQueryable() .Where(config => config.FromState == state) .Select(config => new { Trigger = config.TriggeredBy, TargetState = config.ToState, GuardCondition = config.GuardCondition, IsReentrant = config.IsReentry }) .ToList(); var stateConfig = _stateMachine.Configure(state); foreach (var trig in triggers) { if (trig.GuardCondition == null) { if (trig.IsReentrant) { stateConfig.PermitReentry(trig.Trigger); } else { if (trig.Trigger != null) { stateConfig.Permit(trig?.Trigger, trig?.TargetState); } } } else { if (trig.Trigger != null) { stateConfig.PermitIf(trig?.Trigger, trig?.TargetState, ConditionalGuard(trig?.GuardCondition)); } } } //actions //var actions = workflowDefinition.States.Where(); if (state.SuperState != null) { stateConfig.SubstateOf(state.SuperState); } if (state.EntryAction != null) { stateConfig.OnEntry(t => ExecuteAction(t, state.EntryAction)); } if (state.ExitAction != null) { stateConfig.OnExit(t => ExecuteAction(t, state.ExitAction)); } } // Handle exceptions _stateMachine.OnUnhandledTrigger(OnUnhandledTrigger); // For all the state transitions _stateMachine.OnTransitioned(OnTransitionAction); }
/// <summary> /// Provides entry point to the transitions, can be used for logging /// </summary> /// <param name="source"></param> /// <param name="destination"></param> /// <param name="trigger"></param> /// <param name="reentery"></param> public virtual void WorkflowEngine_OnStateTransition(WorkflowState <string, T> source, WorkflowState <string, T> destination, WorkflowTrigger <string> trigger, bool reentery) { }
/// <summary> /// Allows for the un-handled triggers to be tracked /// </summary> /// <param name="state"></param> /// <param name="trigger"></param> protected virtual void OnUnhandledTrigger(WorkflowState <T, TContext> state, WorkflowTrigger <T> trigger) { OnTriggerUnhandled?.Invoke(state, trigger); }