// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. namespace System.Web.Razor { public abstract class StateMachine { protected delegate StateResult State(); protected abstract State StartState { get; } protected State CurrentState { get; set; } protected virtual TReturn Turn() { if (CurrentState != null) { StateResult result; do { // Keep running until we get a null result or output result = CurrentState(); CurrentState = result.Next; } while (result != null && !result.HasOutput); if (result == null) { return default(TReturn); // Terminated } return result.Output; } return default(TReturn); } /// /// Returns a result indicating that the machine should stop executing and return null output. /// protected StateResult Stop() { return null; } /// /// Returns a result indicating that this state has no output and the machine should immediately invoke the specified state /// /// /// By returning no output, the state machine will invoke the next state immediately, before returning /// controller to the caller of /// protected StateResult Transition(State newState) { return new StateResult(newState); } /// /// Returns a result containing the specified output and indicating that the next call to /// should invoke the provided state. /// protected StateResult Transition(TReturn output, State newState) { return new StateResult(output, newState); } /// /// Returns a result indicating that this state has no output and the machine should remain in this state /// /// /// By returning no output, the state machine will re-invoke the current state again before returning /// controller to the caller of /// protected StateResult Stay() { return new StateResult(CurrentState); } /// /// Returns a result containing the specified output and indicating that the next call to /// should re-invoke the current state. /// protected StateResult Stay(TReturn output) { return new StateResult(output, CurrentState); } protected class StateResult { public StateResult(State next) { HasOutput = false; Next = next; } public StateResult(TReturn output, State next) { HasOutput = true; Output = output; Next = next; } public bool HasOutput { get; set; } public TReturn Output { get; set; } public State Next { get; set; } } } }