/// <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.");
            }
        }
        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);
        }