Skip to content

Commit f274305

Browse files
authored
✨ feature: Create OnStateChanged Method (#6)
1 parent e9c2415 commit f274305

File tree

4 files changed

+73
-7
lines changed

4 files changed

+73
-7
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- OnStateChanged method
13+
1014
## [0.1.0] - 2025-04-23
1115

1216
### Added

TJC.StateMachine.Tests/Mocks/RevolverMock.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
namespace TJC.StateMachine.Tests.Mocks
22
{
3-
internal class RevolverMock()
4-
: StateMachineBase<RevolverStates>(RevolverStates.Loaded)
3+
internal class RevolverMock() : StateMachineBase<RevolverStates>(RevolverStates.Loaded)
54
{
65
public int BulletsLoaded { get; private set; } = 6;
76

7+
internal uint StateChanges = 0;
8+
89
public bool TryShoot()
910
{
1011
switch (State)
@@ -17,7 +18,9 @@ public bool TryShoot()
1718
State = RevolverStates.Empty;
1819
return true;
1920
default:
20-
throw new InvalidOperationException($"Unknown State [{State}] for method {nameof(TryShoot)}");
21+
throw new InvalidOperationException(
22+
$"Unknown State [{State}] for method {nameof(TryShoot)}"
23+
);
2124
}
2225
}
2326

@@ -26,5 +29,10 @@ public void Reload()
2629
BulletsLoaded = 6;
2730
State = RevolverStates.Loaded;
2831
}
32+
33+
protected override void OnStateChanged()
34+
{
35+
StateChanges++;
36+
}
2937
}
30-
}
38+
}

TJC.StateMachine.Tests/Tests/RevolverMockTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,40 @@ public void EnsureReloadingResetsBulletsTo6()
5757
revolver.Reload();
5858
Assert.AreEqual(6, revolver.BulletsLoaded);
5959
}
60+
61+
[TestMethod]
62+
public void EnsureEmptyingChangesStateAndReloadingChangesStateAgain()
63+
{
64+
var revolver = new RevolverMock();
65+
66+
Assert.AreEqual<uint>(0, revolver.StateChanges);
67+
68+
revolver.TryShoot();
69+
revolver.TryShoot();
70+
revolver.TryShoot();
71+
revolver.TryShoot();
72+
revolver.TryShoot();
73+
revolver.TryShoot();
74+
75+
Assert.AreEqual<uint>(1, revolver.StateChanges);
76+
77+
revolver.Reload();
78+
79+
Assert.AreEqual<uint>(2, revolver.StateChanges);
80+
}
81+
82+
[TestMethod]
83+
public void EnsureReloadingMultipleTimesDoesNotChangeState()
84+
{
85+
var revolver = new RevolverMock();
86+
87+
Assert.AreEqual<uint>(0, revolver.StateChanges);
88+
89+
revolver.Reload();
90+
revolver.Reload();
91+
revolver.Reload();
92+
93+
Assert.AreEqual<uint>(0, revolver.StateChanges);
94+
}
6095
}
6196
}

TJC.StateMachine/StateMachineBase.cs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,30 @@
55
/// </summary>
66
/// <typeparam name="T">State Type.</typeparam>
77
/// <param name="initialState">Initial State of the State Machine.</param>
8-
public class StateMachineBase<T>(T initialState)
8+
public abstract class StateMachineBase<T>(T initialState)
99
{
10+
private T _state = initialState;
11+
1012
/// <summary>
1113
/// State of the state machine.
1214
/// </summary>
13-
protected T State { get; set; } = initialState;
15+
protected T State
16+
{
17+
get => _state;
18+
set
19+
{
20+
if (Equals(_state, value))
21+
return;
22+
_state = value;
23+
OnStateChanged();
24+
}
25+
}
26+
27+
/// <summary>
28+
/// Called on state change.
29+
/// Can be used to add tracing &amp; debugging.
30+
/// Should not be used to notify of state changes externally.
31+
/// </summary>
32+
protected abstract void OnStateChanged();
1433
}
15-
}
34+
}

0 commit comments

Comments
 (0)