blob: 395596e7b194b44946ec59f43d10476e1c0e09bd (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
// 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<TReturn>
{
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);
}
/// <summary>
/// Returns a result indicating that the machine should stop executing and return null output.
/// </summary>
protected StateResult Stop()
{
return null;
}
/// <summary>
/// Returns a result indicating that this state has no output and the machine should immediately invoke the specified state
/// </summary>
/// <remarks>
/// By returning no output, the state machine will invoke the next state immediately, before returning
/// controller to the caller of <see cref="Turn"/>
/// </remarks>
protected StateResult Transition(State newState)
{
return new StateResult(newState);
}
/// <summary>
/// Returns a result containing the specified output and indicating that the next call to
/// <see cref="Turn"/> should invoke the provided state.
/// </summary>
protected StateResult Transition(TReturn output, State newState)
{
return new StateResult(output, newState);
}
/// <summary>
/// Returns a result indicating that this state has no output and the machine should remain in this state
/// </summary>
/// <remarks>
/// By returning no output, the state machine will re-invoke the current state again before returning
/// controller to the caller of <see cref="Turn"/>
/// </remarks>
protected StateResult Stay()
{
return new StateResult(CurrentState);
}
/// <summary>
/// Returns a result containing the specified output and indicating that the next call to
/// <see cref="Turn"/> should re-invoke the current state.
/// </summary>
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; }
}
}
}
|