Skip to content

Instantly share code, notes, and snippets.

@JamesTryand
Created January 23, 2023 10:35
Show Gist options
  • Save JamesTryand/c430894cf40f29e39a63bc98fdc77574 to your computer and use it in GitHub Desktop.
Save JamesTryand/c430894cf40f29e39a63bc98fdc77574 to your computer and use it in GitHub Desktop.
Abusing yield to expose internal state machine
Console.WriteLine();
var statemachine = new StateMachineInstance();
statemachine.State2();
statemachine.State3();
statemachine.State4();
Console.ReadLine();
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();
}
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