Created
January 23, 2023 10:35
-
-
Save JamesTryand/c430894cf40f29e39a63bc98fdc77574 to your computer and use it in GitHub Desktop.
Abusing yield to expose internal state machine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Console.WriteLine(); | |
var statemachine = new StateMachineInstance(); | |
statemachine.State2(); | |
statemachine.State3(); | |
statemachine.State4(); | |
Console.ReadLine(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Collections; | |
using System.Reflection; | |
public abstract class StateMachine { | |
protected Action Action; | |
protected IEnumerator CurrentState; | |
protected void Init() { | |
var type = GetType(); | |
foreach (var field in type.GetFields( | |
BindingFlags.Public | | |
BindingFlags.Instance). | |
Where(f => f.FieldType == typeof(Action))) { | |
field.SetValue(this, BuildAction()); | |
} | |
} | |
public StateMachine() | |
{ | |
Init(); | |
CurrentState = MoveState().GetEnumerator(); | |
CurrentState.MoveNext(); | |
} | |
protected Action BuildAction() { | |
Action x = null; | |
x = () => { | |
Action = x; | |
CurrentState.MoveNext(); | |
}; | |
return x; | |
} | |
protected static void Inaction(string excuse) { | |
throw new InvalidOperationException(string.Format($"Error with {excuse}")); | |
} | |
public abstract IEnumerable MoveState(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using System.Collections.Generic; | |
using System.Collections; | |
using System.Reflection; | |
public class StateMachineInstance : StateMachine { | |
public readonly Action State1; | |
public readonly Action State2; | |
public readonly Action State3; | |
public readonly Action State4; | |
public override IEnumerable MoveState() { | |
state1: | |
Console.WriteLine("state1"); | |
yield return null; | |
if (Action == State2) { goto state2; } | |
Inaction("state1"); | |
state2: | |
Console.WriteLine("state2"); | |
yield return null; | |
if (Action == State1) { goto state1; } | |
if (Action == State3) { goto state3; } | |
Inaction("state2"); | |
state3: | |
Console.WriteLine("state3"); | |
yield return null; | |
if (Action == State3) { goto state3; } | |
if (Action == State4) { goto state4; } | |
Inaction("state3"); | |
state4: | |
Console.WriteLine("state4"); | |
yield return null; | |
if (Action == State1) { goto state1; } | |
Inaction("state4"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment