From 4a98da1ad7e90da50f82d8735affa478cb2a86a8 Mon Sep 17 00:00:00 2001 From: HenningTorsteinsenBouvet <henning.torsteinsen@bouvet.no> Date: Tue, 21 May 2024 07:35:57 +0200 Subject: [PATCH] Remove getDestination, and use Destination property instead. Only dynamic transition needs a GetDestination, so it still has it. Updated tests according to changes. --- src/Stateless/DynamicTriggerBehaviour.cs | 3 +-- src/Stateless/IgnoredTriggerBehaviour.cs | 6 ------ src/Stateless/InternalTriggerBehaviour.cs | 6 ------ src/Stateless/ReentryTriggerBehaviour.cs | 7 ------- src/Stateless/StateMachine.Async.cs | 9 +++++---- src/Stateless/StateMachine.cs | 13 ++++++++----- src/Stateless/TransitioningTriggerBehaviour.cs | 6 ------ src/Stateless/TriggerBehaviour.cs | 4 +--- .../IgnoredTriggerBehaviourFixture.cs | 13 +++++++++---- .../SynchronizationContextFixture.cs | 5 ++--- .../TransitioningTriggerBehaviourFixture.cs | 3 +-- 11 files changed, 27 insertions(+), 48 deletions(-) diff --git a/src/Stateless/DynamicTriggerBehaviour.cs b/src/Stateless/DynamicTriggerBehaviour.cs index 99e550d4..ed694f9e 100644 --- a/src/Stateless/DynamicTriggerBehaviour.cs +++ b/src/Stateless/DynamicTriggerBehaviour.cs @@ -17,10 +17,9 @@ public DynamicTriggerBehaviour(TTrigger trigger, Func<object[], TState> destinat TransitionInfo = info ?? throw new ArgumentNullException(nameof(info)); } - public override bool ResultsInTransitionFrom(TState source, object[] args, out TState destination) + public void GetDestinationState(TState source, object[] args, out TState destination) { destination = _destination(args); - return true; } } } diff --git a/src/Stateless/IgnoredTriggerBehaviour.cs b/src/Stateless/IgnoredTriggerBehaviour.cs index 753dc819..cb396f1e 100644 --- a/src/Stateless/IgnoredTriggerBehaviour.cs +++ b/src/Stateless/IgnoredTriggerBehaviour.cs @@ -8,12 +8,6 @@ public IgnoredTriggerBehaviour(TTrigger trigger, TransitionGuard transitionGuard : base(trigger, transitionGuard) { } - - public override bool ResultsInTransitionFrom(TState source, object[] args, out TState destination) - { - destination = default(TState); - return false; - } } } } diff --git a/src/Stateless/InternalTriggerBehaviour.cs b/src/Stateless/InternalTriggerBehaviour.cs index 3966a945..328ef769 100644 --- a/src/Stateless/InternalTriggerBehaviour.cs +++ b/src/Stateless/InternalTriggerBehaviour.cs @@ -14,12 +14,6 @@ protected InternalTriggerBehaviour(TTrigger trigger, TransitionGuard guard) : ba public abstract void Execute(Transition transition, object[] args); public abstract Task ExecuteAsync(Transition transition, object[] args); - public override bool ResultsInTransitionFrom(TState source, object[] args, out TState destination) - { - destination = source; - return false; - } - public class Sync : InternalTriggerBehaviour { public Action<Transition, object[]> InternalAction { get; } diff --git a/src/Stateless/ReentryTriggerBehaviour.cs b/src/Stateless/ReentryTriggerBehaviour.cs index 29ecc344..95df24e9 100644 --- a/src/Stateless/ReentryTriggerBehaviour.cs +++ b/src/Stateless/ReentryTriggerBehaviour.cs @@ -14,13 +14,6 @@ public ReentryTriggerBehaviour(TTrigger trigger, TState destination, TransitionG { _destination = destination; } - - public override bool ResultsInTransitionFrom(TState source, object[] args, out TState destination) - { - destination = _destination; - return true; - } } - } } diff --git a/src/Stateless/StateMachine.Async.cs b/src/Stateless/StateMachine.Async.cs index 919dedda..f69d0065 100644 --- a/src/Stateless/StateMachine.Async.cs +++ b/src/Stateless/StateMachine.Async.cs @@ -219,22 +219,23 @@ async Task InternalFireOneAsync(TTrigger trigger, params object[] args) await HandleReentryTriggerAsync(args, representativeState, transition); break; } - case DynamicTriggerBehaviour _ when result.Handler.ResultsInTransitionFrom(source, args, out var destination): + case DynamicTriggerBehaviour handler: { + handler.GetDestinationState(source, args, out var destination); // Handle transition, and set new state; reentry is permitted from dynamic trigger behaviours. var transition = new Transition(source, destination, trigger, args); await HandleTransitioningTriggerAsync(args, representativeState, transition); break; } - case TransitioningTriggerBehaviour _ when result.Handler.ResultsInTransitionFrom(source, args, out var destination): + case TransitioningTriggerBehaviour handler: { // If a trigger was found on a superstate that would cause unintended reentry, don't trigger. - if (source.Equals(destination)) + if (source.Equals(handler.Destination)) break; // Handle transition, and set new state - var transition = new Transition(source, destination, trigger, args); + var transition = new Transition(source, handler.Destination, trigger, args); await HandleTransitioningTriggerAsync(args, representativeState, transition); break; diff --git a/src/Stateless/StateMachine.cs b/src/Stateless/StateMachine.cs index bb9fa877..a28c5f48 100644 --- a/src/Stateless/StateMachine.cs +++ b/src/Stateless/StateMachine.cs @@ -390,11 +390,13 @@ private void InternalFireQueued(TTrigger trigger, params object[] args) /// </summary> /// <param name="trigger"></param> /// <param name="args"></param> - void InternalFireOne(TTrigger trigger, params object[] args) + private void InternalFireOne(TTrigger trigger, params object[] args) { // If this is a trigger with parameters, we must validate the parameter(s) if (_triggerConfiguration.TryGetValue(trigger, out TriggerWithParameters configuration)) + { configuration.ValidateParameters(args); + } var source = State; var representativeState = GetRepresentation(source); @@ -420,22 +422,23 @@ void InternalFireOne(TTrigger trigger, params object[] args) HandleReentryTrigger(args, representativeState, transition); break; } - case DynamicTriggerBehaviour _ when result.Handler.ResultsInTransitionFrom(source, args, out var destination): + case DynamicTriggerBehaviour handler: { + handler.GetDestinationState(source, args, out var destination); // Handle transition, and set new state; reentry is permitted from dynamic trigger behaviours. var transition = new Transition(source, destination, trigger, args); HandleTransitioningTrigger(args, representativeState, transition); break; } - case TransitioningTriggerBehaviour _ when result.Handler.ResultsInTransitionFrom(source, args, out var destination): + case TransitioningTriggerBehaviour handler: { // If a trigger was found on a superstate that would cause unintended reentry, don't trigger. - if (source.Equals(destination)) + if (source.Equals(handler.Destination)) break; // Handle transition, and set new state - var transition = new Transition(source, destination, trigger, args); + var transition = new Transition(source, handler.Destination, trigger, args); HandleTransitioningTrigger(args, representativeState, transition); break; diff --git a/src/Stateless/TransitioningTriggerBehaviour.cs b/src/Stateless/TransitioningTriggerBehaviour.cs index 269b95e1..417a8cf2 100644 --- a/src/Stateless/TransitioningTriggerBehaviour.cs +++ b/src/Stateless/TransitioningTriggerBehaviour.cs @@ -12,12 +12,6 @@ public TransitioningTriggerBehaviour(TTrigger trigger, TState destination, Trans { Destination = destination; } - - public override bool ResultsInTransitionFrom(TState source, object[] args, out TState destination) - { - destination = Destination; - return true; - } } } } diff --git a/src/Stateless/TriggerBehaviour.cs b/src/Stateless/TriggerBehaviour.cs index 331ec520..f878e6e1 100644 --- a/src/Stateless/TriggerBehaviour.cs +++ b/src/Stateless/TriggerBehaviour.cs @@ -37,7 +37,7 @@ protected TriggerBehaviour(TTrigger trigger, TransitionGuard guard) internal ICollection<Func<object[], bool>> Guards =>_guard.Guards; /// <summary> - /// GuardConditionsMet is true if all of the guard functions return true + /// GuardConditionsMet is true if all the guard functions return true /// or if there are no guard functions /// </summary> public bool GuardConditionsMet(params object[] args) => _guard.GuardConditionsMet(args); @@ -47,8 +47,6 @@ protected TriggerBehaviour(TTrigger trigger, TransitionGuard guard) /// whose guard function returns false /// </summary> public ICollection<string> UnmetGuardConditions(object[] args) => _guard.UnmetGuardConditions(args); - - public abstract bool ResultsInTransitionFrom(TState source, object[] args, out TState destination); } } } diff --git a/test/Stateless.Tests/IgnoredTriggerBehaviourFixture.cs b/test/Stateless.Tests/IgnoredTriggerBehaviourFixture.cs index 63d120ab..de516805 100644 --- a/test/Stateless.Tests/IgnoredTriggerBehaviourFixture.cs +++ b/test/Stateless.Tests/IgnoredTriggerBehaviourFixture.cs @@ -8,8 +8,12 @@ public class IgnoredTriggerBehaviourFixture [Fact] public void StateRemainsUnchanged() { - var ignored = new StateMachine<State, Trigger>.IgnoredTriggerBehaviour(Trigger.X, null); - Assert.False(ignored.ResultsInTransitionFrom(State.B, new object[0], out _)); + var sm = new StateMachine<State, Trigger>(State.A); + sm.Configure(State.A).Ignore(Trigger.X); + + sm.Fire(Trigger.X); + + Assert.Equal(State.A, sm.State); } [Fact] @@ -21,7 +25,7 @@ public void ExposesCorrectUnderlyingTrigger() Assert.Equal(Trigger.X, ignored.Trigger); } - protected bool False(params object[] args) + private bool False(params object[] args) { return false; } @@ -35,7 +39,7 @@ public void WhenGuardConditionFalse_IsGuardConditionMetIsFalse() Assert.False(ignored.GuardConditionsMet()); } - protected bool True(params object[] args) + private bool True(params object[] args) { return true; } @@ -48,6 +52,7 @@ public void WhenGuardConditionTrue_IsGuardConditionMetIsTrue() Assert.True(ignored.GuardConditionsMet()); } + [Fact] public void IgnoredTriggerMustBeIgnoredSync() { diff --git a/test/Stateless.Tests/SynchronizationContextFixture.cs b/test/Stateless.Tests/SynchronizationContextFixture.cs index 26eaccf6..c4f8cacd 100644 --- a/test/Stateless.Tests/SynchronizationContextFixture.cs +++ b/test/Stateless.Tests/SynchronizationContextFixture.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -90,7 +89,7 @@ public async Task Activation_of_state_with_superstate_should_retain_SyncContext( sm.Configure(State.A) .OnActivateAsync(CaptureThenLoseSyncContext) .SubstateOf(State.B); - ; + sm.Configure(State.B) .OnActivateAsync(CaptureThenLoseSyncContext); @@ -110,7 +109,7 @@ public async Task Deactivation_of_state_with_superstate_should_retain_SyncContex sm.Configure(State.A) .OnDeactivateAsync(CaptureThenLoseSyncContext) .SubstateOf(State.B); - ; + sm.Configure(State.B) .OnDeactivateAsync(CaptureThenLoseSyncContext); diff --git a/test/Stateless.Tests/TransitioningTriggerBehaviourFixture.cs b/test/Stateless.Tests/TransitioningTriggerBehaviourFixture.cs index 6c739560..486113ff 100644 --- a/test/Stateless.Tests/TransitioningTriggerBehaviourFixture.cs +++ b/test/Stateless.Tests/TransitioningTriggerBehaviourFixture.cs @@ -8,8 +8,7 @@ public class TransitioningTriggerBehaviourFixture public void TransitionsToDestinationState() { var transitioning = new StateMachine<State, Trigger>.TransitioningTriggerBehaviour(Trigger.X, State.C, null); - Assert.True(transitioning.ResultsInTransitionFrom(State.B, new object[0], out State destination)); - Assert.Equal(State.C, destination); + Assert.Equal(State.C, transitioning.Destination); } } }