/// <summary> /// NOTE 1: http://cs.hubfs.net/blogs/hell_is_other_languages/archive/2008/01/16/4565.aspx /// </summary> public void TriggerTransition(TState targetState, dynamic args = default(dynamic)) { Ensure.That <ArgumentException>(targetState != null, "targetState not supplied."); try { if (CurrentState == targetState && !PermitSelfTransition) { throw new Exception(); //refactor to refine exception } if (CurrentState == FinalState) { throw new Exception(); //refactor to refine exception } if ((CurrentState != targetState || (CurrentState == targetState && !BypassTransitionBehaviorForSelfTransition))) { var matches = StateTransitions.Where(t => t.InitialStates.Where(s => s == CurrentState).Any() && t.EndStates.Where(e => e == targetState).Any()); if (matches.Any()) { using (var t = new TransactionScope()) //this could be in-memory transactionalised using the memento pattern, or information could be sent to F# (see NOTE 1) { OnRaiseBeforeEveryTransition(); CurrentState.ExitAction(args); matches.First().TransitionAction(targetState, this, args); targetState.EntryAction(args); CurrentState = targetState; OnRaiseAfterEveryTransition(); t.Complete(); } } else { if (Parent == null) { throw new Exception(); //to be caught below, refactor } Parent.TriggerTransition(targetState, args); } } } catch (Exception e) { throw new InvalidStateTransitionException <TState>(CurrentState, targetState, innerException: e); } }