Skip to content

Commit a7cf7f0

Browse files
committed
Base structure
1 parent 6e464d3 commit a7cf7f0

19 files changed

+1261
-0
lines changed

SimpleStateMachineLibrary.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29806.167
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStateMachineLibrary", "SimpleStateMachineLibrary\SimpleStateMachineLibrary.csproj", "{047A9390-803D-4964-B512-546D19B62066}"
77
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{7EE69DED-8322-4467-89E3-692CC55F2503}"
9+
EndProject
810
Global
911
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1012
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
1517
{047A9390-803D-4964-B512-546D19B62066}.Debug|Any CPU.Build.0 = Debug|Any CPU
1618
{047A9390-803D-4964-B512-546D19B62066}.Release|Any CPU.ActiveCfg = Release|Any CPU
1719
{047A9390-803D-4964-B512-546D19B62066}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{7EE69DED-8322-4467-89E3-692CC55F2503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{7EE69DED-8322-4467-89E3-692CC55F2503}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{7EE69DED-8322-4467-89E3-692CC55F2503}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{7EE69DED-8322-4467-89E3-692CC55F2503}.Release|Any CPU.Build.0 = Release|Any CPU
1824
EndGlobalSection
1925
GlobalSection(SolutionProperties) = preSolution
2026
HideSolutionNode = FALSE
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using SimpleStateMachineLibrary.Helpers;
2+
using SimpleStateMachineLibrary.StateMachines;
3+
4+
5+
namespace SimpleStateMachineLibrary.Datas
6+
{
7+
public partial class Data : NamedObject
8+
{
9+
public object Value { get; set; }
10+
11+
public Data(StateMachine stateMachine, string nameData, object valueData = null) : base(stateMachine, nameData)
12+
{
13+
Value = valueData;
14+
}
15+
16+
public Data Delete()
17+
{
18+
return this.StateMachine.DeleteData(this);
19+
}
20+
21+
public Data TryDelete()
22+
{
23+
return this.StateMachine.TryDeleteData(this);
24+
}
25+
}
26+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using SimpleStateMachineLibrary.Helpers;
2+
using SimpleStateMachineLibrary.StateMachines;
3+
using System.Xml.Linq;
4+
5+
namespace SimpleStateMachineLibrary.Datas
6+
{
7+
public partial class Data : NamedObject
8+
{
9+
10+
public static XElement ToXElement(Data data)
11+
{
12+
Check.NamedObject(data);
13+
XElement element = new XElement("Data");
14+
element.Add(new XAttribute("Name", data.Name));
15+
element.Add(new XAttribute("Value", data.Value.ToString()));
16+
return element;
17+
}
18+
19+
public XElement ToXElement()
20+
{
21+
XElement element = new XElement("Transition");
22+
element.Add(new XAttribute("Name", this.Name));
23+
element.Add(new XAttribute("Value", this.Value.ToString()));
24+
return element;
25+
}
26+
27+
public static Data FromXElement(StateMachine stateMachine, XElement data)
28+
{
29+
stateMachine = Check.Object(stateMachine);
30+
data = Check.Object(data);
31+
32+
string Name = data.Attribute("Name")?.Value;
33+
string Value = data.Attribute("Value")?.Value;
34+
return stateMachine.AddData(Name, Value);
35+
}
36+
}
37+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace SimpleStateMachineLibrary.Helpers
5+
{
6+
public class Check
7+
{
8+
public static string Name(string name)
9+
{
10+
if (String.IsNullOrEmpty(name))
11+
throw new ArgumentNullException("Name must be not Empty");
12+
return name;
13+
}
14+
15+
public static TObject Object<TObject>(TObject objectRequested)
16+
{
17+
if (Equals(objectRequested, default(TObject)))
18+
throw new ArgumentNullException(String.Format("Object of type {0} must be not null", typeof(TObject).ToString()));
19+
return objectRequested;
20+
}
21+
22+
public static TObject NamedObject<TObject>(TObject objectRequested) where TObject : NamedObject
23+
{
24+
Check.Object(objectRequested);
25+
Check.Name(objectRequested.Name);
26+
return objectRequested;
27+
}
28+
29+
private static bool _Contains<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool needContains, bool exeption) where TObject : NamedObject
30+
{
31+
dictionary = Check.Object(dictionary);
32+
nameObject = Check.Name(nameObject);
33+
34+
if (needContains == dictionary.ContainsKey(nameObject))
35+
return true;
36+
if (exeption)
37+
if (needContains)
38+
throw new KeyNotFoundException(String.Format("Element with name {0} is not found", nameObject));
39+
else
40+
throw new ArgumentException(String.Format("Element with name {0} already exists", nameObject));
41+
return false;
42+
}
43+
44+
private static bool _Contains<TObject>(Dictionary<string, TObject> dictionary, TObject objectRequested, bool needContains, bool exeption) where TObject : NamedObject
45+
{
46+
dictionary = Check.Object(dictionary);
47+
objectRequested = Check.Object(objectRequested);
48+
49+
if (needContains == dictionary.ContainsValue(objectRequested))
50+
return true;
51+
52+
if (exeption)
53+
if (needContains)
54+
throw new KeyNotFoundException(String.Format("Element of type {0} not found", typeof(TObject).ToString()));
55+
else
56+
throw new ArgumentException(String.Format("Element of type {0} already exists", typeof(TObject).ToString()));
57+
return false;
58+
}
59+
60+
61+
public static bool Contains<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool exeption = true) where TObject : NamedObject
62+
{
63+
return _Contains(dictionary, nameObject, true, exeption);
64+
}
65+
66+
public static bool Contains<TObject>(Dictionary<string, TObject> dictionary, TObject objectRequested, bool exeption = true) where TObject : NamedObject
67+
{
68+
return _Contains(dictionary, objectRequested, true, exeption);
69+
}
70+
71+
72+
public static bool NotContains<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool exeption = true) where TObject : NamedObject
73+
{
74+
return _Contains(dictionary, nameObject, false, exeption);
75+
}
76+
77+
public static bool NotContains<TObject>(Dictionary<string, TObject> dictionary, TObject objectRequested, bool exeption = true) where TObject : NamedObject
78+
{
79+
return _Contains(dictionary, objectRequested, false, exeption);
80+
}
81+
82+
83+
public static TObject Remove<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool exeption = true) where TObject : NamedObject
84+
{
85+
dictionary = Check.Object(dictionary);
86+
nameObject = Check.Name(nameObject);
87+
88+
TObject removedObj = default(TObject);
89+
dictionary?.TryGetValue(nameObject, out removedObj);
90+
91+
if (removedObj== default(TObject))
92+
{
93+
if (exeption)
94+
throw new KeyNotFoundException(String.Format("Element with name {0} is not deleted because not found. ", nameObject));
95+
else
96+
return default(TObject);
97+
}
98+
99+
dictionary.Remove(nameObject);
100+
return removedObj;
101+
}
102+
103+
public static TObject Remove<TObject>(Dictionary<string, TObject> dictionary, TObject obj, bool exeption = true) where TObject : NamedObject
104+
{
105+
dictionary = Check.Object(dictionary);
106+
obj = Check.NamedObject(obj);
107+
108+
TObject removedObj = default(TObject);
109+
dictionary?.TryGetValue(obj.Name, out removedObj);
110+
111+
if (removedObj == default(TObject))
112+
{
113+
if (exeption)
114+
throw new KeyNotFoundException(String.Format("Element with name {0} is not deleted because not found. ", obj.Name));
115+
else
116+
return default(TObject);
117+
}
118+
119+
dictionary.Remove(obj.Name);
120+
return removedObj;
121+
}
122+
123+
124+
public static TObject GetElement<TObject>(Dictionary<string, TObject> dictionary, string nameObject, bool exeption = true) where TObject : NamedObject
125+
{
126+
bool contains = Contains(dictionary, nameObject, exeption);
127+
return contains ? dictionary[nameObject]:default(TObject);
128+
}
129+
130+
public static TObject GetElement<TObject>(Dictionary<string, TObject> dictionary, TObject obj, bool exeption = true) where TObject : NamedObject
131+
{
132+
bool contains = Contains(dictionary, obj, exeption);
133+
return contains? obj:default(TObject);
134+
}
135+
136+
137+
public static TObject AddElement<TObject>(Dictionary<string, TObject> dictionary, TObject obj, bool exeption = true) where TObject : NamedObject
138+
{
139+
return AddElement(dictionary, obj?.Name, obj, exeption);
140+
}
141+
142+
public static TObject AddElement<TObject>(Dictionary<string, TObject> dictionary, string name, TObject obj, bool exeption = true) where TObject : NamedObject
143+
{
144+
obj = Check.NamedObject(obj);
145+
bool nonContains = NotContains(dictionary, name, exeption);
146+
147+
if (nonContains)
148+
return default(TObject);
149+
150+
dictionary.Add(name, obj);
151+
return obj;
152+
}
153+
}
154+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using SimpleStateMachineLibrary.StateMachines;
2+
3+
namespace SimpleStateMachineLibrary.Helpers
4+
{
5+
public abstract class NamedObject
6+
{
7+
public string Name { get; }
8+
public StateMachine StateMachine { get; }
9+
10+
public NamedObject(StateMachine stateMachine, string nameObject)
11+
{
12+
StateMachine = Check.Object(stateMachine);
13+
14+
Name = Check.Name(nameObject);
15+
}
16+
17+
}
18+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
using System.Collections.Generic;
2+
using System.Xml.Linq;
3+
4+
using SimpleStateMachineLibrary.States;
5+
using SimpleStateMachineLibrary.Transitions;
6+
using SimpleStateMachineLibrary.Helpers;
7+
using SimpleStateMachineLibrary.Datas;
8+
using System;
9+
10+
namespace SimpleStateMachineLibrary.StateMachines
11+
{
12+
public partial class StateMachine
13+
{
14+
private Dictionary<string, State> _states = new Dictionary<string, State>();
15+
16+
private Dictionary<string, Transition> _transitions = new Dictionary<string, Transition>();
17+
18+
private Dictionary<string, Data> _data = new Dictionary<string, Data>();
19+
20+
public State CurrentState { get; internal set; }
21+
22+
public Transition CurrentTransition{ get; internal set; }
23+
24+
public State StartState { get; protected set; }
25+
26+
public State EndState { get; protected set; }
27+
28+
public StateMachine()
29+
{
30+
31+
}
32+
33+
public StateMachine(XDocument xDocument)
34+
{
35+
FromXDocument(this, xDocument);
36+
}
37+
38+
public StateMachine(string xDocumentPath)
39+
{
40+
FromXDocument(this, xDocumentPath);
41+
}
42+
43+
44+
private Transition _nextTransition { get; set; }
45+
46+
private Dictionary<string, object> _currentParameters { get; set; }
47+
48+
private Dictionary<string, object> _nextParameters { get; set; }
49+
50+
51+
52+
private void CheckStartState()
53+
{
54+
if (StartState != null)
55+
{
56+
throw new ArgumentException(String.Format("Start state already set. It's {0} ", StartState.Name));
57+
}
58+
}
59+
60+
private void CheckEndState()
61+
{
62+
if (EndState != null)
63+
{
64+
throw new ArgumentException(String.Format("End state already set. It's {0} ", StartState.Name));
65+
}
66+
}
67+
68+
private void CheckCurrentTransition()
69+
{
70+
if (CurrentTransition == null)
71+
{
72+
throw new ArgumentException(String.Format("State with name \"{0}\" doesn't invoke transition", CurrentState.Name));
73+
}
74+
}
75+
76+
public State SetStartState(State state)
77+
{
78+
CheckStartState();
79+
StartState = State(Check.Object(state));
80+
return StartState;
81+
}
82+
83+
public State SetStartState(string stateName)
84+
{
85+
CheckEndState();
86+
StartState = State(Check.Object(stateName));
87+
return StartState;
88+
}
89+
90+
public State SetEndState(State state)
91+
{
92+
EndState = State(Check.Object(state));
93+
return EndState;
94+
}
95+
96+
public State SetEndState(string stateName)
97+
{
98+
EndState = State(Check.Object(stateName));
99+
return EndState;
100+
}
101+
102+
public void InvokeTransition(string nameTransition)
103+
{
104+
_nextTransition = Check.GetElement(_transitions, nameTransition, true);
105+
}
106+
107+
public void InvokeTransitionWithParameters(string nameTransition, Dictionary<string, object> parameters)
108+
{
109+
InvokeTransition(nameTransition);
110+
111+
_nextParameters = parameters;
112+
}
113+
114+
public void Start(Dictionary<string, object> startParameters = null)
115+
{
116+
CurrentState = StartState;
117+
CurrentState.Entry(startParameters);
118+
CurrentState.Exit(startParameters);
119+
while (CurrentState != EndState)
120+
{
121+
_currentParameters = _nextParameters;
122+
_nextParameters = null;
123+
124+
CurrentTransition = _nextTransition;
125+
_nextTransition = null;
126+
127+
CheckCurrentTransition();
128+
CurrentState = null;
129+
CurrentTransition.Invoke(_currentParameters);
130+
CurrentState = CurrentTransition.StateTo;
131+
CurrentTransition = null;
132+
133+
CurrentState.Entry(_currentParameters);
134+
CurrentState.Exit(_currentParameters);
135+
}
136+
137+
}
138+
139+
}
140+
}

0 commit comments

Comments
 (0)