Пример #1
0
        private static void Dispatch <TInternalState, TEvent>(TEvent evnt
                                                              , IMachineState <TInternalState> internalState
                                                              , InternalState <TInternalState> currentState
                                                              , IReadOnlyDictionary <InternalState <TInternalState>, InternalState <TInternalState> > relations
                                                              , IEnumerable <Func <object, object> > eventInterceptors
                                                              , MachineConfiguration <TInternalState> config
                                                              , bool outerTransitionsTakePrecedence
                                                              , Func <string, InternalState <TInternalState> > lookup)
        {
            var currentStates = Misc <TInternalState> .FindAllStates(relations, currentState);

            if (!outerTransitionsTakePrecedence)
            {
                currentStates.Reverse();
            }

            var nextState = DispatchToStates(evnt, internalState, currentStates, eventInterceptors, config, lookup);

            if (nextState != null && nextState != currentStates.Last())
            {
                nextState = TransitionTo((object)evnt, internalState, relations, nextState, eventInterceptors, false, config, lookup);
            }

            if (nextState != null)
            {
                UpdateStateHistories(internalState, relations, nextState);
            }
        }
Пример #2
0
        private static InternalState <TInternalState> TransitionTo <TInternalState>(
            object evnt
            , IMachineState <TInternalState> machineState
            , IReadOnlyDictionary <InternalState <TInternalState>, InternalState <TInternalState> > relations
            , InternalState <TInternalState> transitionToState
            , IEnumerable <Func <object, object> > eventInterceptors
            , bool exitInnerStatesFirst
            , MachineConfiguration <TInternalState> config
            , Func <string, InternalState <TInternalState> > lookup)
        {
            config.Logger(string.Format("SM:{0}:{1} = State: {2} -> {3} on ^{4} = '{5}'"
                                        , config.Name
                                        , config.GetUniqueId(machineState.CurrentInternalState)
                                        , machineState.CurrentState.Name
                                        , transitionToState.Name
                                        , evnt.GetType().Name
                                        , config.LogEvents(evnt)));

            var _currentStates = Misc <TInternalState> .FindAllStates(relations, machineState.CurrentState);

            var _nextStates = Misc <TInternalState> .FindAllStates(relations, transitionToState);

            while (machineState.StateHistory.ContainsKey(transitionToState))
            {
                var nextTransitionToState = machineState.StateHistory[transitionToState];
                transitionToState = nextTransitionToState;
                _nextStates.Add(nextTransitionToState);
            }

            var entryConditionsToRun = _nextStates.Except(_currentStates);
            var exitConditionsToRun  = _currentStates.Except(_nextStates);

            if (exitInnerStatesFirst)
            {
                entryConditionsToRun.Reverse();
                exitConditionsToRun.Reverse();
            }

            // Dispatch and do not transition...
            var newState = DispatchToStates(new Events.ExitEvent(), machineState, exitConditionsToRun, eventInterceptors, config, lookup);

            machineState.ChangeState(_nextStates.Last());

            // Dispath entry event - transition if neccesary  and do not transition...
            newState = DispatchToStates(new Events.EntryEvent(), machineState, entryConditionsToRun, eventInterceptors, config, lookup);
            if (newState != null)
            {
                transitionToState = TransitionTo(evnt, machineState, relations, newState, eventInterceptors, exitInnerStatesFirst, config, lookup);
            }

            return(transitionToState);
        }
Пример #3
0
        internal MachineDefinition(
            IReadOnlyList <InternalState <TInternalState> > registeredStates,
            IReadOnlyDictionary <string, string> parentStates,
            IReadOnlyList <Func <object, object> > eventInterceptors,
            MachineConfiguration <TInternalState> config,
            IState initialState,
            Dictionary <BuilderState <TInternalState>, BuilderState <TInternalState> > stateHistories)
        {
            if (registeredStates == null)
            {
                throw new ArgumentNullException(nameof(registeredStates));
            }

            if (parentStates == null)
            {
                throw new ArgumentNullException(nameof(parentStates));
            }

            if (eventInterceptors == null)
            {
                throw new ArgumentNullException(nameof(eventInterceptors));
            }

            if (initialState == null)
            {
                throw new ArgumentNullException(nameof(initialState));
            }

            if (stateHistories == null)
            {
                throw new ArgumentNullException(nameof(stateHistories));
            }

            _log = config.Logger;

            RegisteredState   = registeredStates;
            EventInterceptors = eventInterceptors;
            Config            = config;
            InitialState      = LookupRegisteredState(initialState.Name);
            StateHistories    = stateHistories.ToDictionary(x => LookupRegisteredState(x.Key.Name), x => LookupRegisteredState(x.Value.Name));;
            ParentStates      = parentStates.ToDictionary(
                x => LookupRegisteredState(x.Key),
                x => LookupRegisteredState(x.Value));

            Log(registeredStates);
        }
Пример #4
0
        private static InternalState <TInternalState> Execute <TInternalState, TEvent>(TEvent evnt,
                                                                                       IMachineState <TInternalState> internalState,
                                                                                       MachineConfiguration <TInternalState> config,
                                                                                       InternalState <TInternalState> finalTransitionState,
                                                                                       InternalState <TInternalState> currentState,
                                                                                       Func <string, InternalState <TInternalState> > lookup)
        {
            var handler = currentState.Handlers[evnt.GetType()];

            Action <string> log =
                str => config.Logger($"SM:{config.Name}:{config.GetUniqueId(internalState.CurrentInternalState)} = State: {currentState.Name} - {str}");

            foreach (var action in handler.TransistionDefinitions)
            {
                if (action.GuardCondition(internalState.CurrentInternalState, evnt))
                {
                    action.Action?.Invoke(internalState.CurrentInternalState, evnt, log);

                    if (action.TransitionTo != null)
                    {
                        finalTransitionState = finalTransitionState ?? lookup(action.TransitionTo);
                    }
                }
            }

            return(finalTransitionState);
        }
Пример #5
0
        private static InternalState <TInternalState> DispatchToStates <TInternalState, TEvent>(TEvent evnt
                                                                                                , IMachineState <TInternalState> internalState
                                                                                                , IEnumerable <InternalState <TInternalState> > statesToDispatchTo
                                                                                                , IEnumerable <Func <object, object> > eventInterceptors
                                                                                                , MachineConfiguration <TInternalState> config
                                                                                                , Func <string, InternalState <TInternalState> > lookup)
        {
            TEvent evntToDispatch = ExecuteInterceptorsForEvent(evnt, eventInterceptors);

            if (evntToDispatch == null)
            {
                // Do not dispatch a null event!
                return(null);
            }

            InternalState <TInternalState> finalTransitionState = null;
            Type eventType = evnt.GetType();

            foreach (var currentState in statesToDispatchTo)
            {
                if (currentState.Handlers.ContainsKey(eventType))
                {
                    finalTransitionState = Execute(evnt, internalState, config, finalTransitionState, currentState, lookup);
                }
                else if (eventType != typeof(Events.EntryEvent) & eventType != typeof(Events.ExitEvent))
                {
                    if (currentState.Handlers.ContainsKey(typeof(Events.DefaultEvent)))
                    {
                        finalTransitionState = Execute(new Events.DefaultEvent(), internalState, config, finalTransitionState, currentState, lookup);
                    }
                }

                if (eventType != typeof(Events.EntryEvent) & eventType != typeof(Events.ExitEvent))
                {
                    // Always run an AnyEvent() -
                    if (currentState.Handlers.ContainsKey(typeof(Events.AnyEvent)))
                    {
                        finalTransitionState = Execute(new Events.AnyEvent(), internalState, config, finalTransitionState, currentState, lookup);
                    }
                }
            }

            return(finalTransitionState);
        }