/// <summary> /// Restore the state of this state machine from a previously-created string (from calling the <see cref="Serialize()"/> method). /// </summary> /// <param name="serialized">String created by <see cref="Serialize()"/></param> public void Deserialize(string serialized) { this.Reset(); var childState = this.serializer.Deserialize(this, serialized); var intermediateStates = new List <TState>(); for (TState state = childState; state != null; state = state.ParentStateMachine.ParentState) { intermediateStates.Add(state); } ChildStateMachine <TState> stateMachine = this; foreach (var state in intermediateStates.AsEnumerable().Reverse()) { // We should never hit this Trace.Assert(stateMachine != null, $"Unable to deserialize from \"{serialized}\": the previous state has no child state machine. This should not happen"); // This will throw if the state doesn't belong to the state machine stateMachine.SetCurrentState(state); stateMachine = state.ChildStateMachine; } // Did we run out of identifiers? // We need to check this to avoid internal inconsistency if (stateMachine != null) { throw new StateMachineSerializationException($"Unable to deserialize from \"{serialized}\": a parent state has the child state machine {stateMachine}, but no information is present in the serialized string saying what its state should be. Make sure you're deserializing into exactly the same state machine as created the serialized string."); } }
internal void Initialize(string name, ChildStateMachine <TState> parentStateMachine) { this.isInitialized = true; // If they've subclassed this and set Name themselves, then provided 'null' in CreateState, // don't override what they set if (!String.IsNullOrWhiteSpace(name)) { this.Name = name; } this.ParentStateMachine = parentStateMachine; }
private void EnterChildStateMachine(ChildStateMachine <TState> childStateMachine, TState from, IEvent @event, bool isInnerTransition, object eventData, EventFireMethod eventFireMethod) { childStateMachine.SetCurrentState(childStateMachine.InitialState); this.EnterState(new StateHandlerInfo <TState>(from, childStateMachine.InitialState, @event, isInnerTransition, eventData, eventFireMethod)); if (childStateMachine.InitialState.ChildStateMachine != null) { this.EnterChildStateMachine(childStateMachine.InitialState.ChildStateMachine, from, @event, isInnerTransition, eventData, eventFireMethod); } }
private void ExitChildStateMachine(ChildStateMachine <TState> childStateMachine, TState to, IEvent @event, bool isInnerTransition, object eventData, EventFireMethod eventFireMethod) { if (childStateMachine.CurrentState != null && childStateMachine.CurrentState.ChildStateMachine != null) { this.ExitChildStateMachine(childStateMachine.CurrentState.ChildStateMachine, to, @event, isInnerTransition, eventData, eventFireMethod); } this.ExitState(new StateHandlerInfo <TState>(childStateMachine.CurrentState, to, @event, isInnerTransition, eventData, eventFireMethod)); childStateMachine.SetCurrentState(null); }
private static IEnumerable <TState> StateIterator(ChildStateMachine <TState> stateMachine) { // Depth-first recursive iteration of all states // State machine is not fully initialised if (stateMachine.InitialState == null) { throw new StateMachineSerializationException($"Unable to serialize state machine {stateMachine} as it is not fully initialised (it has no initial state)."); } foreach (var state in stateMachine.States) { yield return(state); if (state.ChildStateMachine != null) { foreach (var subState in StateIterator(state.ChildStateMachine)) { yield return(subState); } } } }
internal State(string name, ChildStateMachine parentStateMachine) { this.ParentStateMachine = parentStateMachine; this.innerState = new StateInner <State>(name, parentStateMachine.InnerStateMachine.Kernel); }
internal State(string name, TStateData data, ChildStateMachine <TStateData> parentStateMachine) { this.Data = data; this.ParentStateMachine = parentStateMachine; this.innerState = new StateInner <State <TStateData> >(name, parentStateMachine.InnerStateMachine.Kernel); }