public override StateTransitionResult <TState, TTrigger> Execute(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { if (currentResult != null && _startState.IsEqual(currentResult.PreviousState) && (_triggerState.IsEqual(currentResult.CurrentState) || _stateMachine.IsInState(parameters.Context, _triggerState))) { StateMutator(parameters.Context, _stateFunction.Invoke(parameters.Context)); var transitioned = !StateAccessor(parameters.Context).IsEqual(_triggerState); var result = GetFreshResult(parameters , currentResult , currentResult.StartingState , wasCancelled: false , transitionDefined: true , conditionMet: transitioned); if (transitioned) { NotifyOfTransition(parameters.Context, result); } return(result); } return(GetFreshResult(parameters , currentResult , StateAccessor(parameters.Context) , wasCancelled: false , conditionMet: false , transitionDefined: true)); }
public async Task ExecuteExitActionAsync(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult) { //Is there an action based on the new state? if (_nextStateExitActions.TryGetValue(currentResult.CurrentState, out var action)) { if (parameters.CancellationToken.IsCancellationRequested) { return; } await action.Invoke(parameters.Context, parameters.CancellationToken) .ConfigureAwait(continueOnCapturedContext: false); } //Is there an action for any exit? if (_defaultExitAction != null) { if (parameters.CancellationToken.IsCancellationRequested) { return; } if (_defaultExitAction != null) { await _defaultExitAction.Invoke(parameters.Context, parameters.CancellationToken) .ConfigureAwait(continueOnCapturedContext: false); } } }
public override StateTransitionResult <TState, TTrigger> Execute(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { if (!(parameters.Request is TParam typeSafeParam)) { throw new ArgumentException($"Expected a {typeof(TParam).Name} parameter, but received a {parameters.Request?.GetType().Name ?? "null"}."); } return(ExecutePrim(parameters, currentResult, Condition(parameters.Context, typeSafeParam))); }
public void ExecuteExitAction(T context, StateTransitionResult <TState, TTrigger> currentResult) { //Is there an action based on the new state? if (_nextStateExitActions.TryGetValue(currentResult.CurrentState, out var action)) { action.Invoke(context); } //Is there an action for any exit? _defaultExitAction?.Invoke(context); if (_superState != null && !IsInState(currentResult.CurrentState)) { _superState.ExecuteExitAction(context, currentResult); } }
protected StateTransitionResult <TState, TTrigger> ExecutePrim(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult , bool conditionMet) { var startState = currentResult != null ? currentResult.StartingState : StateAccessor(parameters.Context); if (!conditionMet) { return(GetFreshResult(parameters, currentResult, startState, wasCancelled: false, conditionMet: false, transitionDefined: true)); } StateMutator(parameters.Context, ToState); var transitionResult = GetFreshResult(parameters, currentResult, startState, wasCancelled: false, conditionMet: true, transitionDefined: true); return(transitionResult); }
public override StateTransitionResult <TState, TTrigger> Execute(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { if (currentResult != null && (_triggerState.IsEqual(currentResult.CurrentState) || _stateMachine.IsInState(parameters.Context, _triggerState))) { return(base.Execute(parameters, currentResult)); } return(GetFreshResult(parameters , currentResult , StateAccessor(parameters.Context) , wasCancelled: false , transitionDefined: true , conditionMet: false)); }
public void ExecuteEntryAction(T context, StateTransitionResult <TState, TTrigger> currentResult) { //If there's an entry state for the super state, execute it first if (_superState != null && !IsInState(currentResult.CurrentState)) { _superState.ExecuteEntryAction(context, currentResult); } //Is there an action based on the new state? if (_previousStateEntryActions.TryGetValue(currentResult.PreviousState, out var action)) { action.Invoke(context); } //Is there an action for any entry? _defaultEntryAction?.Invoke(context); }
protected StateTransitionResult <TState, TTrigger> FireTriggerPrim(ExecutionParameters <T, TTrigger> parameters) { StateTransitionResult <TState, TTrigger> result = null; if (Transitions.TryGetValue(parameters.Trigger, out var transitions)) { foreach (var transition in transitions.OrderBy(t => t.Priority)) { result = transition.Execute(parameters); if (result.WasTransitioned) { return(result); } } } return(result); }
protected StateTransitionResult <TState, TTrigger> GetFreshResult(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> previousResult , TState startState , bool transitionDefined , bool conditionMet , bool wasCancelled) { bool wasSuccessful = (transitionDefined && conditionMet && !wasCancelled); return(new StateTransitionResult <TState, TTrigger>(parameters.Trigger , startState , (!wasSuccessful || previousResult == null) ? startState : previousResult.CurrentState , wasSuccessful ? StateAccessor(parameters.Context) : previousResult == null ? startState : previousResult.CurrentState , wasSuccessful ? Name : string.Empty , wasCancelled: wasCancelled , conditionMet: conditionMet , transitionDefined: transitionDefined)); }
private async Task <StateTransitionResult <TState, TTrigger> > FireTriggerPrimAsync(ExecutionParameters <T, TTrigger> parameters) { StateTransitionResult <TState, TTrigger> result = null; if (Transitions.TryGetValue(parameters.Trigger, out var transitions)) { foreach (var transition in transitions.OrderBy(t => t.Priority)) { result = await transition.ExecuteAsync(parameters).ConfigureAwait(continueOnCapturedContext: false); if (result.WasTransitioned) { return(result); } } } return(result); }
public override StateTransitionResult <TState, TTrigger> Execute(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { if (!(parameters.Request is TParam)) { throw new ArgumentException($"Expected a {typeof(TParam).Name} parameter, but received a {parameters.Request?.GetType().Name ?? "null"}."); } if (currentResult != null && (_triggerState.IsEqual(currentResult.CurrentState) || _stateMachine.IsInState(parameters.Context, _triggerState))) { return(base.Execute(parameters, currentResult)); } return(GetFreshResult(parameters , currentResult , StateAccessor(parameters.Context) , wasCancelled: false , transitionDefined: true , conditionMet: false)); }
public override StateTransitionResult <TState, TTrigger> Execute(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { if (!(parameters.Request is TRequest typeSafeParam)) { throw new ArgumentException($"Expected a {typeof(TRequest).Name} parameter, but received a {parameters.Request?.GetType().Name ?? "null"}."); } if (currentResult != null && !parameters.CancellationToken.IsCancellationRequested && _startState.IsEqual(currentResult.PreviousState) && (_triggerState.IsEqual(currentResult.CurrentState) || _stateMachine.IsInState(parameters.Context, _triggerState))) { StateMutator(parameters.Context, _stateFunction(parameters.Context, typeSafeParam)); var transitioned = !StateAccessor(parameters.Context).IsEqual(_triggerState); var result = GetFreshResult(parameters , currentResult , currentResult.StartingState , wasCancelled: false , transitionDefined: true , conditionMet: transitioned); if (transitioned) { NotifyOfTransition(parameters.Context, result); } return(result); } return(GetFreshResult(parameters , currentResult , StateAccessor(parameters.Context) , wasCancelled: parameters.CancellationToken.IsCancellationRequested , transitionDefined: true , conditionMet: false)); }
/// <summary> /// Constructor. /// </summary> /// <param name="parameters">Parameters used for the call to FireTrigger.</param> /// <param name="transitionResult">Details of transitions that occurred during FireTrigger.</param> public TransitionEventArgs(ExecutionParameters <T, TTrigger> parameters, StateTransitionResult <TState, TTrigger> transitionResult) { Parameters = parameters ?? throw new ArgumentNullException(nameof(parameters)); TransitionResult = transitionResult ?? throw new ArgumentNullException(nameof(transitionResult)); }
private StateTransitionResult <TState, TTrigger> executeExitAndEntryActions(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult) { if (currentResult.WasTransitioned && !(currentResult.StartingState.CompareTo(currentResult.PreviousState) == 0 && currentResult.PreviousState.CompareTo(currentResult.CurrentState) == 0)) { _stateConfigurations.TryGetValue(currentResult.PreviousState, out var previousState); //OnExit? ...don't execute if moving to substate if (!IsInState(parameters.Context, currentResult.PreviousState)) { previousState.ExecuteExitAction(parameters.Context, currentResult); } if (_stateConfigurations.TryGetValue(currentResult.CurrentState, out var newState)) { //OnEntry? ...don't execute if moving to superstate if (!previousState.IsInState(currentResult.CurrentState)) { newState.ExecuteEntryAction(parameters.Context, currentResult); } //Auto transitions? var preAutoForwardState = currentResult.CurrentState; var autoTransitionResult = newState.ExecuteAutoTransition(parameters, currentResult); if (autoTransitionResult.WasTransitioned) { //Merge the results currentResult.PreviousState = currentResult.CurrentState; currentResult.CurrentState = autoTransitionResult.CurrentState; currentResult.LastTransitionName = autoTransitionResult.LastTransitionName; } //See if we have more actions from the auto transition if (currentResult.CurrentState.CompareTo(preAutoForwardState) != 0) { currentResult = executeExitAndEntryActions(parameters, currentResult); } } } //Reentry? else if (_stateConfigurations.TryGetValue(currentResult.CurrentState, out var reenteredState)) { reenteredState.ExecuteReentryAction(parameters.Context, currentResult); } //Send notifications var transitionEventArgs = new TransitionEventArgs <T, TState, TTrigger>(parameters, currentResult); if (!currentResult.WasTransitioned) { if (!currentResult.TransitionDefined) { OnTriggerNotConfigured?.Invoke(this, transitionEventArgs); } OnNoTransition?.Invoke(this, transitionEventArgs); } return(currentResult); }
public override async Task <StateTransitionResult <TState, TTrigger> > ExecuteAsync(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { if (currentResult != null && !parameters.CancellationToken.IsCancellationRequested && _startState.IsEqual(currentResult.PreviousState) && (_triggerState.IsEqual(currentResult.CurrentState) || _stateMachine.IsInState(parameters.Context, _triggerState))) { return(await base.ExecuteAsync(parameters, currentResult)); } return(GetFreshResult(parameters , currentResult , StateAccessor(parameters.Context) , wasCancelled: parameters.CancellationToken.IsCancellationRequested , transitionDefined: true , conditionMet: false)); }
public override async Task <StateTransitionResult <TState, TTrigger> > ExecuteAsync(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { if (!(parameters.Request is TParam typeSafeParam)) { throw new ArgumentException($"Expected a {typeof(TParam).Name} parameter, but received a {parameters.Request?.GetType().Name ?? "null"}."); } var startState = currentResult != null ? currentResult.StartingState : StateAccessor(parameters.Context); if (parameters.CancellationToken.IsCancellationRequested) { if (currentResult != null) { return(currentResult); } return(new StateTransitionResult <TState, TTrigger>(parameters.Trigger , startState , startState , startState , lastTransitionName: string.Empty , wasCancelled: true)); } var toState = await StateFuncAsync(parameters.Context, typeSafeParam, parameters.CancellationToken) .ConfigureAwait(continueOnCapturedContext: false); return(ExecuteFinalizeAsync(parameters, currentResult, startState, toState)); }
public void ExecuteReentryAction(T context, StateTransitionResult <TState, TTrigger> currentResult) { _superState?.ExecuteReentryAction(context, currentResult); _reentryAction?.Invoke(context); }
public override async Task <StateTransitionResult <TState, TTrigger> > ExecuteAsync(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { if (!(parameters.Request is TParam typeSafeParam)) { throw new ArgumentException($"Expected a {typeof(TParam).Name} parameter, but received a {parameters.Request?.GetType().Name ?? "null"}."); } var startState = currentResult != null ? currentResult.StartingState : StateAccessor(parameters.Context); if (parameters.CancellationToken.IsCancellationRequested) { return(GetFreshResult(parameters , currentResult , startState , transitionDefined: true , conditionMet: false , wasCancelled: true)); } if (!await ConditionAsync(parameters.Context, typeSafeParam, parameters.CancellationToken) .ConfigureAwait(continueOnCapturedContext: false)) { return(GetFreshResult(parameters, currentResult, startState, transitionDefined: true, conditionMet: false, wasCancelled: parameters.CancellationToken.IsCancellationRequested)); } StateMutator(parameters.Context, ToState); var transitionResult = currentResult == null ? new StateTransitionResult <TState, TTrigger>(parameters.Trigger, startState, startState, ToState, Name) : new StateTransitionResult <TState, TTrigger>(parameters.Trigger, startState, currentResult.CurrentState, ToState, Name); NotifyOfTransition(parameters.Context, transitionResult); return(transitionResult); }
public async Task <StateTransitionResult <TState, TTrigger> > ExecuteAutoTransitionAsync(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult) { if (AutoTransitions.TryGetValue(parameters.Trigger, out var triggerTransitions)) { foreach (var transition in triggerTransitions.OrderBy(t => t.Priority)) { var localResult = await transition.ExecuteAsync(parameters, currentResult) .ConfigureAwait(continueOnCapturedContext: false); if (localResult.WasTransitioned) { return(localResult); } } } //Check for a super state and just return the incoming currentResult if no successful auto transitions return(_superState != null ? await _superState.ExecuteAutoTransitionAsync(parameters, currentResult).ConfigureAwait(continueOnCapturedContext: false) : new StateTransitionResult <TState, TTrigger>(parameters.Trigger , currentResult.StartingState , currentResult.PreviousState , currentResult.CurrentState , currentResult.LastTransitionName , transitionDefined: true , wasCancelled: parameters.CancellationToken.IsCancellationRequested , conditionMet: false)); }
private async Task <StateTransitionResult <TState, TTrigger> > executeExitAndEntryActionsAsync(ExecutionParameters <T, TTrigger> parameters, StateTransitionResult <TState, TTrigger> currentResult) { var currentState = StateAccessor(parameters.Context); if (currentResult.WasTransitioned && !currentState.Equals(currentResult.StartingState)) { _stateConfigurations.TryGetValue(currentResult.PreviousState, out var previousState); //OnExit? ...don't execute if moving to substate if (!IsInState(parameters.Context, currentResult.PreviousState)) { await previousState.ExecuteExitActionAsync(parameters, currentResult) .ConfigureAwait(continueOnCapturedContext: false); } if (_stateConfigurations.TryGetValue(currentResult.CurrentState, out var newState)) { //OnEntry? ...don't execute if moving to superstate if (!previousState.IsInState(currentResult.CurrentState)) { await newState.ExecuteEntryActionAsync(parameters, currentResult) .ConfigureAwait(continueOnCapturedContext: false); } //AutoForward? var preAutoForwardState = currentResult.CurrentState; var autoTransitionResult = await newState.ExecuteAutoTransitionAsync(parameters, currentResult) .ConfigureAwait(continueOnCapturedContext: false); if (autoTransitionResult.WasTransitioned) { //Merge the results currentResult.PreviousState = currentResult.CurrentState; currentResult.CurrentState = autoTransitionResult.CurrentState; currentResult.LastTransitionName = autoTransitionResult.LastTransitionName; } //See if we have more actions from the auto transition if (preAutoForwardState.CompareTo(currentResult.CurrentState) != 0) { await executeExitAndEntryActionsAsync(parameters, currentResult) .ConfigureAwait(continueOnCapturedContext: false); } } } //Reentry? else if (_stateConfigurations.TryGetValue(currentResult.CurrentState, out var reenteredState)) { await reenteredState.ExecuteReentryActionAsync(parameters, currentResult) .ConfigureAwait(continueOnCapturedContext: false); } //Send notifications var transitionEventArgs = new TransitionEventArgs <T, TState, TTrigger>(parameters, currentResult); if (!currentResult.WasTransitioned) { if (!currentResult.TransitionDefined) { OnTriggerNotConfigured?.Invoke(this, transitionEventArgs); } OnNoTransition?.Invoke(this, transitionEventArgs); } return(currentResult); }
protected void NotifyOfTransition(T context, StateTransitionResult <TState, TTrigger> transitionResult) { OnTransitionedEvent?.Invoke(context, transitionResult); }
public override StateTransitionResult <TState, TTrigger> Execute(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { return(ExecutePrim(parameters, currentResult, Condition(parameters.Context))); }
public override StateTransitionResult <TState, TTrigger> Execute(ExecutionParameters <T, TTrigger> parameters, StateTransitionResult <TState, TTrigger> currentResult = null) { if (!(parameters.Request is TParam typeSafeParam)) { throw new ArgumentException($"Expected a {typeof(TParam).Name} parameter, but received a {parameters.Request?.GetType().Name ?? "null"}."); } var startState = currentResult != null ? currentResult.StartingState : StateAccessor(parameters.Context); var toState = StateFunc(parameters.Context, typeSafeParam); var transitioned = !toState.IsEqual(startState); if (transitioned) { StateMutator(parameters.Context, toState); } var transitionResult = GetFreshResult(parameters, currentResult, startState, transitionDefined: true, wasCancelled: false, conditionMet: transitioned); if (transitioned) { NotifyOfTransition(parameters.Context, transitionResult); } return(transitionResult); }
public override async Task <StateTransitionResult <TState, TTrigger> > ExecuteAsync(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { var startState = currentResult != null ? currentResult.StartingState : StateAccessor(parameters.Context); if (parameters.CancellationToken.IsCancellationRequested) { return(GetFreshResult(parameters, currentResult, startState, wasCancelled: true, transitionDefined: true, conditionMet: false)); } if (!await ConditionAsync(parameters.Context, parameters.CancellationToken) .ConfigureAwait(continueOnCapturedContext: false)) { return(GetFreshResult(parameters, currentResult, startState, wasCancelled: parameters.CancellationToken.IsCancellationRequested, transitionDefined: true, conditionMet: false)); } StateMutator(parameters.Context, ToState); var transitionResult = GetFreshResult(parameters, currentResult, startState, wasCancelled: false, conditionMet: true, transitionDefined: true); NotifyOfTransition(parameters.Context, transitionResult); return(transitionResult); }
public override StateTransitionResult <TState, TTrigger> Execute(ExecutionParameters <T, TTrigger> parameters, StateTransitionResult <TState, TTrigger> currentResult = null) { var startState = currentResult != null ? currentResult.StartingState : StateAccessor(parameters.Context); var toState = StateFunc(parameters.Context); StateMutator(parameters.Context, toState); var transitioned = !StateAccessor(parameters.Context).IsEqual(startState); var transitionResult = GetFreshResult(parameters, currentResult, startState, wasCancelled: false, transitionDefined: true, conditionMet: transitioned); if (transitioned) { NotifyOfTransition(parameters.Context, transitionResult); } return(transitionResult); }
public async Task ExecuteReentryActionAsync(ExecutionParameters <T, TTrigger> parameters, StateTransitionResult <TState, TTrigger> currentResult) { if (_superState != null) { await _superState.ExecuteReentryActionAsync(parameters, currentResult) .ConfigureAwait(continueOnCapturedContext: false); } if (_reentryAction != null && !parameters.CancellationToken.IsCancellationRequested) { await _reentryAction.Invoke(parameters.Context, parameters.CancellationToken) .ConfigureAwait(continueOnCapturedContext: false); } }
public virtual Task <StateTransitionResult <TState, TTrigger> > ExecuteAsync(ExecutionParameters <T, TTrigger> parameters , StateTransitionResult <TState, TTrigger> currentResult = null) { throw new NotImplementedException("Inheritted classes must override this method. Ensure you're calling the correct overloaded version."); }