public async Task <TState> Execute() { var previousState = StatedEntity.State; if (TransitionToInvoke == null) { throw new TransitionNotSpecifiedException(); } try { var transition = GetRequestedTransition; IStateHandler <TEntity> transitionHandler = transition?.OnTransitioning?.Invoke(); var validationResult = await IsPreconditionOk().ConfigureAwait(false); if (validationResult is TransitionValidationFailed failedResult && transitionHandler != null) { StatedEntity.State.InitFailedTransitionResult( previousState, TransitionToInvoke, failedResult); if (transitionHandler is IPrevalidation <TEntity> pv) { await pv.OnValidationFailed(StatedEntity, failedResult).ConfigureAwait(false); } return(StatedEntity.State); } ITransitionExecutionResult transitionResult = null; Exception transitionException = null; if (transition.OnTransitioning != null) { try { transitionHandler = transition.OnTransitioning.Invoke(); if (transitionHandler is IBeforeTransition <TEntity> bth) { await bth.OnPrepareTransition(StatedEntity).ConfigureAwait(false); } transitionResult = await transitionHandler.ExecuteTransition(StatedEntity).ConfigureAwait(false); } catch (Exception e) { transitionException = e; IsTransitionSuccessful = false; transitionResult = CreateFailedResult(previousState, TransitionToInvoke, "TransitionFailed", e); } } if (transitionResult is TransitionSuccessful successfulResult) { StatedEntity.State = transition.StateTransitionOnSuccess.Compile()(StatedEntity.State); if (transitionHandler is IAfterSuccessfulTransition <TEntity> ast) { await ast.OnSuccessfulTransition(StatedEntity, successfulResult).ConfigureAwait(false); } StatedEntity.State.InitSuccessfulTransitionResult(successfulResult); ActionOnSuccess?.Invoke(StatedEntity, StatedEntity.State); await StateEngine.NotifyStateChange(StatedEntity).ConfigureAwait(false); return(StatedEntity.State); } if (transitionHandler is IAfterFailedTransition <TEntity> aft) { await aft.OnFailedTransition(StatedEntity, transitionResult as TransitionFailed).ConfigureAwait(false); } if (transition.OnTransitionFailed == null) { throw new TransitionFailedException(transition.StateTransitionOnSuccess.TransitionName <TState, TStateEnum>(), $"{previousState}", transitionException); } throw new TransitionRollbackFailedException( transition.StateTransitionOnFailed?.TransitionName <TState, TStateEnum>() ?? "[rollback undefined]", $"{previousState}", transitionException); } catch (Exception ex) { StatedEntity.State.InitFailedTransitionResult(previousState, TransitionToInvoke, "TransitionExecutionFailed", ex); StatedEntity.State.TransitionResult.AddMessageArg("", ""); ActionOnError?.Invoke(StatedEntity, StatedEntity.State); return(StatedEntity.State); } }