using System.Collections.Generic;
var newState = State.Open(this);
if (newState != State) Console.WriteLine($"Door wih color {Color} was opened");
else Console.WriteLine($"Door wih color {Color} remains in state {State.GetType().Name}");
var newState = State.Close(this);
if (newState != State) Console.WriteLine($"Door wih color {Color} was closed");
else Console.WriteLine($"Door wih color {Color} remains in state {State.GetType().Name}");
public delegate bool Condition(Door door);
public struct ConditionKey
public readonly Type FromState;
public readonly Type ToState;
public ConditionKey(Type fromState, Type toState)
private readonly DoorOpen _open;
private readonly DoorClosed _closed;
public DoorStates(IDictionary<ConditionKey, Condition> conditions)
_open = new DoorOpen(conditions[new ConditionKey(typeof(DoorOpen), typeof(DoorClosed))]);
_closed = new DoorClosed(conditions[new ConditionKey(typeof(DoorClosed), typeof(DoorOpen))]);
_open.ClosedState = _closed;
_closed.OpenState = _open;
public IDoorState GenerateStateMachine()
public interface IDoorState
IDoorState Open(Door door);
IDoorState Close(Door door);
public class DoorOpen : IDoorState
public DoorClosed ClosedState;
private readonly Condition _canClose;
public DoorOpen(Condition canClose)
public IDoorState Open(Door _)
public IDoorState Close(Door door)
if (_canClose(door)) return ClosedState;
public class DoorClosed : IDoorState
public DoorOpen OpenState;
private readonly Condition _canOpen;
public DoorClosed(Condition canOpen)
public IDoorState Open(Door door)
if (_canOpen(door)) return OpenState;
public IDoorState Close(Door _)
public static void Main()
var conditions = new Dictionary<ConditionKey, Condition>
[new ConditionKey(typeof(DoorOpen), typeof(DoorClosed))] = ((Door door) => door.Color == "red"),
[new ConditionKey(typeof(DoorClosed), typeof(DoorOpen))] = ((_) => true),
var states = new DoorStates(conditions);
State = states.GenerateStateMachine(),