diff --git a/src/Automatonymous.Tests/Activity_Specs.cs b/src/Automatonymous.Tests/Activity_Specs.cs
index 80d5834..3834e86 100644
--- a/src/Automatonymous.Tests/Activity_Specs.cs
+++ b/src/Automatonymous.Tests/Activity_Specs.cs
@@ -50,10 +50,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.TransitionTo(Running));
@@ -101,10 +97,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
-
- Event(() => Initialized);
-
Initially(
When(Initialized)
.TransitionTo(Running));
@@ -159,10 +151,6 @@ class InstanceStateMachine :
public InstanceStateMachine()
{
- State(() => Running);
-
- Event(() => Initialized);
-
Initially(
When(Initialized)
.Finalize());
@@ -233,11 +221,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Initializing);
- State(() => Running);
-
- Event(() => Initialized);
-
During(Initializing,
When(Initialized)
.TransitionTo(Running));
diff --git a/src/Automatonymous.Tests/Anytime_Specs.cs b/src/Automatonymous.Tests/Anytime_Specs.cs
index 17ac414..06937c6 100644
--- a/src/Automatonymous.Tests/Anytime_Specs.cs
+++ b/src/Automatonymous.Tests/Anytime_Specs.cs
@@ -84,12 +84,6 @@ class TestStateMachine :
{
public TestStateMachine()
{
- State(() => Ready);
-
- Event(() => Init);
- Event(() => Hello);
- Event(() => EventA);
-
Initially(
When(Init)
.TransitionTo(Ready));
diff --git a/src/Automatonymous.Tests/AsyncActivity_Specs.cs b/src/Automatonymous.Tests/AsyncActivity_Specs.cs
index efbdc65..2f56605 100644
--- a/src/Automatonymous.Tests/AsyncActivity_Specs.cs
+++ b/src/Automatonymous.Tests/AsyncActivity_Specs.cs
@@ -67,10 +67,6 @@ public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
-
- Event(() => Create);
-
During(Initial,
When(Create)
.Then(() => new SetValueAsyncActivity())
diff --git a/src/Automatonymous.Tests/Automatonymous.Tests.csproj b/src/Automatonymous.Tests/Automatonymous.Tests.csproj
index 3d19f09..bba89d1 100644
--- a/src/Automatonymous.Tests/Automatonymous.Tests.csproj
+++ b/src/Automatonymous.Tests/Automatonymous.Tests.csproj
@@ -53,6 +53,7 @@
SolutionVersion.cs
+
diff --git a/src/Automatonymous.Tests/AutomatonymousStateMachine_Specs.cs b/src/Automatonymous.Tests/AutomatonymousStateMachine_Specs.cs
new file mode 100644
index 0000000..3db6264
--- /dev/null
+++ b/src/Automatonymous.Tests/AutomatonymousStateMachine_Specs.cs
@@ -0,0 +1,141 @@
+// Copyright 2011 Chris Patterson, Dru Sellers
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+// this file except in compliance with the License. You may obtain a copy of the
+// License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+namespace Automatonymous.Tests
+{
+ using System.Linq;
+
+ using NUnit.Framework;
+
+
+ [TestFixture]
+ public class Using_a_simple_state_machine
+ {
+ [Test]
+ public void Should_register_all_state_properties()
+ {
+ var stateMachine = new TestStateMachine();
+
+ var states = stateMachine.States.ToList();
+
+ Assert.That(states, Has.Count.EqualTo(3));
+ }
+
+ [Test]
+ public void Should_register_inherited_initial_state_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.States, Contains.Item(stateMachine.Initial));
+ }
+
+ [Test]
+ public void Should_register_inherited_final_state_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.States, Contains.Item(stateMachine.Final));
+ }
+
+ [Test]
+ public void Should_register_declared_state_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.States, Contains.Item(stateMachine.ThisIsAState));
+ }
+
+ [Test]
+ public void Should_initialize_inherited_initial_state_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.Initial, Is.Not.Null);
+ }
+
+ [Test]
+ public void Should_initialize_inherited_final_state_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.Final, Is.Not.Null);
+ }
+
+ [Test]
+ public void Should_initialize_declared_state_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.ThisIsAState, Is.Not.Null);
+ }
+
+ [Test]
+ public void Should_register_all_event_properties()
+ {
+ var stateMachine = new TestStateMachine();
+
+ var events = stateMachine.Events.ToList();
+
+ Assert.That(events, Has.Count.EqualTo(2));
+ }
+
+ [Test]
+ public void Should_register_simple_event_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.Events, Contains.Item(stateMachine.ThisIsASimpleEvent));
+ }
+
+ [Test]
+ public void Should_register_generic_event_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.Events, Contains.Item(stateMachine.ThisIsAnEventConsumingData));
+ }
+
+ [Test]
+ public void Should_initialize_simple_event_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.ThisIsASimpleEvent, Is.Not.Null);
+ }
+
+ [Test]
+ public void Should_initialize_generic_event_property()
+ {
+ var stateMachine = new TestStateMachine();
+
+ Assert.That(stateMachine.ThisIsAnEventConsumingData, Is.Not.Null);
+ }
+
+
+ class Instance
+ {
+ }
+
+
+ class EventData
+ {
+ }
+
+
+ class TestStateMachine : AutomatonymousStateMachine
+ {
+ public State ThisIsAState { get; private set; }
+ public Event ThisIsASimpleEvent { get; private set; }
+ public Event ThisIsAnEventConsumingData { get; private set; }
+ }
+ }
+}
diff --git a/src/Automatonymous.Tests/Combine_Specs.cs b/src/Automatonymous.Tests/Combine_Specs.cs
index 9543aa8..d82941f 100644
--- a/src/Automatonymous.Tests/Combine_Specs.cs
+++ b/src/Automatonymous.Tests/Combine_Specs.cs
@@ -72,12 +72,8 @@ class TestStateMachine :
public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Waiting);
- Event(() => Start);
- Event(() => First);
- Event(() => Second);
- Event(() => Third, x => x.CompositeStatus, First, Second);
+ ComposeEvent(Third, x => x.CompositeStatus, First, Second);
Initially(
When(Start)
@@ -97,4 +93,4 @@ public TestStateMachine()
public Event Third { get; private set; }
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Automatonymous.Tests/DataActivity_Specs.cs b/src/Automatonymous.Tests/DataActivity_Specs.cs
index 3d43c52..51906fe 100644
--- a/src/Automatonymous.Tests/DataActivity_Specs.cs
+++ b/src/Automatonymous.Tests/DataActivity_Specs.cs
@@ -75,11 +75,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
-
- Event(() => Initialized);
- Event(() => PassedValue);
-
During(Initial,
When(Initialized)
.Then((instance, data) => instance.Value = data.Value)
diff --git a/src/Automatonymous.Tests/Declarative_Specs.cs b/src/Automatonymous.Tests/Declarative_Specs.cs
index bf5ed42..1775f71 100644
--- a/src/Automatonymous.Tests/Declarative_Specs.cs
+++ b/src/Automatonymous.Tests/Declarative_Specs.cs
@@ -68,10 +68,6 @@ public TopInstanceStateMachine()
{
InstanceState(x => x.Top);
- State(() => Greeted);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.TransitionTo(Greeted));
@@ -89,10 +85,6 @@ public BottomInstanceStateMachine()
{
InstanceState(x => x.Bottom);
- State(() => Ignored);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.TransitionTo(Ignored));
diff --git a/src/Automatonymous.Tests/Dependency_Specs.cs b/src/Automatonymous.Tests/Dependency_Specs.cs
index 970857d..4497d87 100644
--- a/src/Automatonymous.Tests/Dependency_Specs.cs
+++ b/src/Automatonymous.Tests/Dependency_Specs.cs
@@ -102,10 +102,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
-
- Event(() => Create);
-
During(Initial,
When(Create)
.Then(() => new CalculateValueActivity(new LocalCalculator()))
diff --git a/src/Automatonymous.Tests/EventLift_Specs.cs b/src/Automatonymous.Tests/EventLift_Specs.cs
index a2185c3..33eb84b 100644
--- a/src/Automatonymous.Tests/EventLift_Specs.cs
+++ b/src/Automatonymous.Tests/EventLift_Specs.cs
@@ -50,10 +50,6 @@ class InstanceStateMachine :
{
public InstanceStateMachine()
{
- State(() => Running);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.TransitionTo(Running));
@@ -107,10 +103,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.TransitionTo(Running));
diff --git a/src/Automatonymous.Tests/EventObservable_Specs.cs b/src/Automatonymous.Tests/EventObservable_Specs.cs
index 8913e62..4401263 100644
--- a/src/Automatonymous.Tests/EventObservable_Specs.cs
+++ b/src/Automatonymous.Tests/EventObservable_Specs.cs
@@ -86,10 +86,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.TransitionTo(Running));
diff --git a/src/Automatonymous.Tests/Event_Specs.cs b/src/Automatonymous.Tests/Event_Specs.cs
index 44c8491..b4c4b5a 100644
--- a/src/Automatonymous.Tests/Event_Specs.cs
+++ b/src/Automatonymous.Tests/Event_Specs.cs
@@ -73,9 +73,6 @@ class TestStateMachine :
{
public TestStateMachine()
{
- Event(() => Hello);
- Event(() => EventA);
- Event(() => EventInt);
}
public Event Hello { get; private set; }
diff --git a/src/Automatonymous.Tests/Exception_Specs.cs b/src/Automatonymous.Tests/Exception_Specs.cs
index 98aa374..2dd8041 100644
--- a/src/Automatonymous.Tests/Exception_Specs.cs
+++ b/src/Automatonymous.Tests/Exception_Specs.cs
@@ -84,10 +84,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Failed);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.Try(x => x.Then(instance => instance.Called = true)
@@ -185,10 +181,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Failed);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.Try(x => x.Then(instance => instance.Called = true)
diff --git a/src/Automatonymous.Tests/FilterExpression_Specs.cs b/src/Automatonymous.Tests/FilterExpression_Specs.cs
index f13dc0a..a63079e 100644
--- a/src/Automatonymous.Tests/FilterExpression_Specs.cs
+++ b/src/Automatonymous.Tests/FilterExpression_Specs.cs
@@ -45,11 +45,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => True);
- State(() => False);
-
- Event(() => Thing);
-
During(Initial,
When(Thing, msg => msg.Condition)
.TransitionTo(True),
diff --git a/src/Automatonymous.Tests/Group_Specs.cs b/src/Automatonymous.Tests/Group_Specs.cs
index d76eb16..ce344c0 100644
--- a/src/Automatonymous.Tests/Group_Specs.cs
+++ b/src/Automatonymous.Tests/Group_Specs.cs
@@ -77,10 +77,6 @@ public PitStop()
{
InstanceState(x => x.OverallState);
- State(() => BeingServiced);
-
- Event(() => VehicleArrived);
-
During(Initial,
When(VehicleArrived)
.Then((instance, m) =>
@@ -110,8 +106,6 @@ public FillTank()
{
InstanceState(x => x.FuelState);
- State(() => Filling);
-
Initially(
When(Initial.Enter)
.TransitionTo(Filling));
@@ -140,8 +134,6 @@ public CheckOil()
{
InstanceState(x => x.OilState);
- State(() => AddingOil);
-
Initially(
When(Initial.Enter)
.TransitionTo(AddingOil));
diff --git a/src/Automatonymous.Tests/InstanceLift_Specs.cs b/src/Automatonymous.Tests/InstanceLift_Specs.cs
index a430efc..8f2f309 100644
--- a/src/Automatonymous.Tests/InstanceLift_Specs.cs
+++ b/src/Automatonymous.Tests/InstanceLift_Specs.cs
@@ -53,10 +53,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.TransitionTo(Running));
@@ -111,10 +107,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
-
- Event(() => Initialized);
-
During(Initial,
When(Initialized)
.TransitionTo(Running));
diff --git a/src/Automatonymous.Tests/Introspection_Specs.cs b/src/Automatonymous.Tests/Introspection_Specs.cs
index 9f269a5..e727250 100644
--- a/src/Automatonymous.Tests/Introspection_Specs.cs
+++ b/src/Automatonymous.Tests/Introspection_Specs.cs
@@ -89,15 +89,6 @@ public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- Event(() => Hello);
- Event(() => YelledAt);
- Event(() => Handshake);
- Event(() => Ignored);
-
- State(() => Greeted);
- State(() => Loved);
- State(() => Pissed);
-
Initially(
When(Hello)
.TransitionTo(Greeted));
diff --git a/src/Automatonymous.Tests/Observable_Specs.cs b/src/Automatonymous.Tests/Observable_Specs.cs
index 72f07d1..0974786 100644
--- a/src/Automatonymous.Tests/Observable_Specs.cs
+++ b/src/Automatonymous.Tests/Observable_Specs.cs
@@ -69,11 +69,6 @@ class InstanceStateMachine :
{
public InstanceStateMachine()
{
- State(() => Running);
-
- Event(() => Initialized);
- Event(() => Finish);
-
During(Initial,
When(Initialized)
.TransitionTo(Running));
diff --git a/src/Automatonymous.Tests/SerializeState_Specs.cs b/src/Automatonymous.Tests/SerializeState_Specs.cs
index 0c26c45..c69bfc5 100644
--- a/src/Automatonymous.Tests/SerializeState_Specs.cs
+++ b/src/Automatonymous.Tests/SerializeState_Specs.cs
@@ -55,11 +55,6 @@ public InstanceStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => True);
- State(() => False);
-
- Event(() => Thing);
-
During(Initial,
When(Thing, msg => msg.Condition)
.TransitionTo(True),
diff --git a/src/Automatonymous.Tests/State_Specs.cs b/src/Automatonymous.Tests/State_Specs.cs
index b2af85d..9a0606f 100644
--- a/src/Automatonymous.Tests/State_Specs.cs
+++ b/src/Automatonymous.Tests/State_Specs.cs
@@ -63,8 +63,6 @@ class TestStateMachine :
public TestStateMachine()
{
InstanceState(x => x.CurrentState);
-
- State(() => Running);
}
public State Running { get; private set; }
@@ -144,9 +142,6 @@ public TestStateMachine()
{
InstanceState(x => x.AutomatonymousState);
- State(() => Running);
- Event(() => Started);
-
Initially(
When(Started)
.TransitionTo(Running));
diff --git a/src/Automatonymous.Tests/Transition_Specs.cs b/src/Automatonymous.Tests/Transition_Specs.cs
index d09023b..515f1e9 100644
--- a/src/Automatonymous.Tests/Transition_Specs.cs
+++ b/src/Automatonymous.Tests/Transition_Specs.cs
@@ -75,11 +75,6 @@ class InstanceStateMachine :
{
public InstanceStateMachine()
{
- State(() => Running);
-
- Event(() => Initialized);
- Event(() => Finish);
-
During(Initial,
When(Initialized)
.TransitionTo(Running));
diff --git a/src/Automatonymous.Tests/Visualizer_Specs.cs b/src/Automatonymous.Tests/Visualizer_Specs.cs
index b6b6c62..9e11105 100644
--- a/src/Automatonymous.Tests/Visualizer_Specs.cs
+++ b/src/Automatonymous.Tests/Visualizer_Specs.cs
@@ -88,17 +88,7 @@ class InstanceStateMachine :
{
public InstanceStateMachine()
{
- InstanceState(x => x.CurrentState);
-
- State(() => Running);
- State(() => Suspended);
- State(() => Failed);
-
- Event(() => Initialized);
- Event(() => Finished);
- Event(() => Suspend);
- Event(() => Resume);
- Event(() => Restart);
+ InstanceState(x => x.CurrentState);
During(Initial,
When(Initialized)
diff --git a/src/Automatonymous/AutomatonymousStateMachine.cs b/src/Automatonymous/AutomatonymousStateMachine.cs
index f97f53f..0a1d7ef 100644
--- a/src/Automatonymous/AutomatonymousStateMachine.cs
+++ b/src/Automatonymous/AutomatonymousStateMachine.cs
@@ -13,20 +13,68 @@
namespace Automatonymous
{
using System;
+ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
+
using Activities;
+
using Binders;
+
using Impl;
+
using Internals.Caching;
using Internals.Extensions;
using Internals.Primitives;
+
using Taskell;
+ public abstract class AutomatonymousStateMachine
+ {
+ private static readonly object PropertyLocker = new object();
+ private static readonly IDictionary> Properties = new ConcurrentDictionary>();
+
+ protected static readonly Type OpenGenericDataEventType = typeof (DataEvent<>);
+
+ // TODO: make this an Extension Method of Type
+ private static IEnumerable GetInheritanceChain(Type type, bool includeSelf = true)
+ {
+ var b = includeSelf ? type : type.BaseType;
+
+ while (b != null)
+ {
+ yield return b;
+
+ b = b.BaseType;
+ }
+ }
+
+ protected static IEnumerable GetProperties(Type type)
+ {
+ if (Properties.ContainsKey(type) == false)
+ {
+ lock (PropertyLocker)
+ {
+ if (Properties.ContainsKey(type) == false)
+ {
+ var properties = GetInheritanceChain(type)
+ .SelectMany(x => x.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
+ .ToList();
+
+ Properties[type] = properties;
+ }
+ }
+ }
+
+ return Properties[type];
+ }
+ }
+
public abstract class AutomatonymousStateMachine :
+ AutomatonymousStateMachine,
AcceptStateMachineInspector,
StateMachine
where TInstance : class
@@ -47,11 +95,10 @@ protected AutomatonymousStateMachine()
_eventRaisingObserver = new EventRaisingObserver(_eventCache);
_eventRaisedObserver = new EventRaisedObserver(_eventCache);
- State(() => Initial);
- State(() => Final);
+ RegisterStates();
+ RegisterEvents();
- _instanceStateAccessor = new DefaultInstanceStateAccessor(_stateCache[Initial.Name],
- _stateChangedObservable);
+ _instanceStateAccessor = new DefaultInstanceStateAccessor(_stateCache[Initial.Name], _stateChangedObservable);
}
public void Accept(StateMachineInspector inspector)
@@ -59,17 +106,17 @@ public void Accept(StateMachineInspector inspector)
Initial.Accept(inspector);
_stateCache.Each(x =>
- {
- if (Equals(x, Initial) || Equals(x, Final))
- return;
+ {
+ if (Equals(x, Initial) || Equals(x, Final))
+ return;
- x.Accept(inspector);
- });
+ x.Accept(inspector);
+ });
Final.Accept(inspector);
}
- StateAccessor StateMachine.InstanceStateAccessor
+ public StateAccessor InstanceStateAccessor
{
get { return _instanceStateAccessor; }
}
@@ -85,25 +132,25 @@ State StateMachine.GetState(string name)
void StateMachine.RaiseEvent(Composer composer, TInstance instance, Event @event)
{
composer.Execute(() =>
- {
- State state = _instanceStateAccessor.Get(instance);
+ {
+ State state = _instanceStateAccessor.Get(instance);
- State instanceState = _stateCache[state.Name];
+ State instanceState = _stateCache[state.Name];
- return composer.ComposeEvent(instance, instanceState, @event);
- });
+ return composer.ComposeEvent(instance, instanceState, @event);
+ });
}
void StateMachine.RaiseEvent(Composer composer, TInstance instance, Event @event, TData data)
{
composer.Execute(() =>
- {
- State state = _instanceStateAccessor.Get(instance);
+ {
+ State state = _instanceStateAccessor.Get(instance);
- State instanceState = _stateCache[state.Name];
+ State instanceState = _stateCache[state.Name];
- return composer.ComposeEvent(instance, instanceState, @event, data);
- });
+ return composer.ComposeEvent(instance, instanceState, @event, data);
+ });
}
public State GetState(string name)
@@ -171,17 +218,49 @@ protected void InstanceState(Expression> instanceStatePro
_stateCache[Initial.Name], _stateChangedObservable);
}
- protected void Event(Expression> propertyExpression)
+ void RegisterEvents()
{
- PropertyInfo property = propertyExpression.GetPropertyInfo();
+ var properties = GetProperties(GetType())
+ .Where(x => typeof(Event).IsAssignableFrom(x.PropertyType)); // TODO: this may just need to be equals
- string name = property.Name;
+ foreach (var property in properties)
+ {
+ var name = property.Name;
- var @event = new SimpleEvent(name);
+ Event @event;
- property.SetValue(this, @event);
+ if (property.PropertyType.IsGenericType)
+ {
+ var dataEventType = OpenGenericDataEventType.MakeGenericType(property.PropertyType.GetGenericArguments());
- _eventCache[name] = new StateMachineEvent(@event);
+ @event = (Event)Activator.CreateInstance(dataEventType, name);
+ }
+ else
+ {
+ @event = new SimpleEvent(name);
+ }
+
+ _eventCache[name] = new StateMachineEvent(@event);
+
+ property.SetValue(this, @event);
+ }
+ }
+
+ void RegisterStates()
+ {
+ var properties = GetProperties(GetType())
+ .Where(x => typeof(State).IsAssignableFrom(x.PropertyType)); // TODO: this may just need to be equals
+
+ foreach (var property in properties)
+ {
+ var name = property.Name;
+
+ State state = new StateImpl(name, _eventRaisingObserver, _eventRaisedObserver);
+
+ _stateCache[name] = state;
+
+ property.SetValue(this, state);
+ }
}
///
@@ -189,42 +268,46 @@ protected void Event(Expression> propertyExpression)
/// off the required events have been raised. Note that required events cannot be in the initial
/// state since it would cause extra instances of the state machine to be created
///
- /// The composite event
+ /// The composite event
/// The property in the instance used to track the state of the composite event
/// The events that must be raised before the composite event is raised
- protected void Event(Expression> propertyExpression,
+ protected void ComposeEvent(Event @event,
Expression> trackingPropertyExpression,
params Event[] events)
{
+ // TODO: check @event for null???
+
if (events == null)
+ {
throw new ArgumentNullException("events");
+ }
+
if (events.Length > 31)
+ {
throw new ArgumentException("No more than 31 events can be combined into a single event");
+ }
+
if (events.Length == 0)
+ {
throw new ArgumentException("At least one event must be specified for a composite event");
+ }
+
if (events.Any(x => x == null))
+ {
throw new ArgumentException("One or more events specified has not yet been initialized");
+ }
- PropertyInfo eventProperty = propertyExpression.GetPropertyInfo();
PropertyInfo trackingPropertyInfo = trackingPropertyExpression.GetPropertyInfo();
- string name = eventProperty.Name;
-
- var @event = new SimpleEvent(name);
-
- eventProperty.SetValue(this, @event);
-
- _eventCache[name] = new StateMachineEvent(@event);
-
var complete = new CompositeEventStatus(Enumerable.Range(0, events.Length)
- .Aggregate(0, (current, x) => current | (1 << x)));
+ .Aggregate(0, (current, x) => current | (1 << x)));
for (int i = 0; i < events.Length; i++)
{
int flag = 1 << i;
var activity = new CompositeEventActivity(trackingPropertyInfo, flag, complete,
- (consumer, instance) => ((StateMachine)this).RaiseEvent(consumer, instance, @event));
+ (consumer, instance) => ((StateMachine) this).RaiseEvent(consumer, instance, @event));
foreach (var state in _stateCache.Where(x => !Equals(x, Initial)))
{
@@ -235,32 +318,6 @@ protected void Event(Expression> propertyExpression,
}
}
- protected void Event(Expression>> propertyExpression)
- {
- PropertyInfo property = propertyExpression.GetPropertyInfo();
-
- string name = property.Name;
-
- var @event = new DataEvent(name);
-
- property.SetValue(this, @event);
-
- _eventCache[name] = new StateMachineEvent(@event);
- }
-
- protected void State(Expression> propertyExpression)
- {
- PropertyInfo property = propertyExpression.GetPropertyInfo();
-
- string name = property.Name;
-
- var state = new StateImpl(name, _eventRaisingObserver, _eventRaisedObserver);
-
- property.SetValue(this, state);
-
- _stateCache[name] = state;
- }
-
protected void During(State state, params IEnumerable>[] activities)
{
EventActivity[] eventActivities = activities.SelectMany(x => x).ToArray();
@@ -338,13 +395,13 @@ void BindTransitionEvents(State state, IEnumerable activity.Where(x => IsTransitionEvent(state, x.Event)));
foreach (var eventActivity in eventActivities)
- During(state, new[] {eventActivity});
+ During(state, new[] { eventActivity });
}
bool IsTransitionEvent(State state, Event eevent)
{
return Equals(eevent, state.Enter) || Equals(eevent, state.BeforeEnter)
- || Equals(eevent, state.AfterLeave) || Equals(eevent, state.Leave);
+ || Equals(eevent, state.AfterLeave) || Equals(eevent, state.Leave);
}
protected void Finally(Func, EventActivityBinder> activityCallback)
@@ -372,4 +429,4 @@ protected EventActivityBinder When(Event @event,
return new DataEventActivityBinder(this, @event, filterExpression);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Automatonymous/CompositeEventStatus.cs b/src/Automatonymous/CompositeEventStatus.cs
index 16242c0..9330343 100644
--- a/src/Automatonymous/CompositeEventStatus.cs
+++ b/src/Automatonymous/CompositeEventStatus.cs
@@ -61,4 +61,4 @@ public void Set(int flag)
_bits |= flag;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Automatonymous/Event.cs b/src/Automatonymous/Event.cs
index 7519eab..68548fe 100644
--- a/src/Automatonymous/Event.cs
+++ b/src/Automatonymous/Event.cs
@@ -27,4 +27,4 @@ public interface Event :
Event
{
}
-}
\ No newline at end of file
+}
diff --git a/src/Automatonymous/State.cs b/src/Automatonymous/State.cs
index eba6880..9900b97 100644
--- a/src/Automatonymous/State.cs
+++ b/src/Automatonymous/State.cs
@@ -53,4 +53,4 @@ public interface State :
void Bind(EventActivity activity);
}
-}
\ No newline at end of file
+}
diff --git a/src/MassTransit/MassTransit.AutomatonymousTests/CompositeEvent_Specs.cs b/src/MassTransit/MassTransit.AutomatonymousTests/CompositeEvent_Specs.cs
index d80face..37d4ab4 100644
--- a/src/MassTransit/MassTransit.AutomatonymousTests/CompositeEvent_Specs.cs
+++ b/src/MassTransit/MassTransit.AutomatonymousTests/CompositeEvent_Specs.cs
@@ -94,12 +94,8 @@ class TestStateMachine :
public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Waiting);
- Event(() => Start);
- Event(() => First);
- Event(() => Second);
- Event(() => Third, x => x.CompositeStatus, First, Second);
+ ComposeEvent(Third, x => x.CompositeStatus, First, Second);
Initially(
When(Start)
diff --git a/src/MassTransit/MassTransit.AutomatonymousTests/Fault_Specs.cs b/src/MassTransit/MassTransit.AutomatonymousTests/Fault_Specs.cs
index a7d00e8..cd8db1b 100644
--- a/src/MassTransit/MassTransit.AutomatonymousTests/Fault_Specs.cs
+++ b/src/MassTransit/MassTransit.AutomatonymousTests/Fault_Specs.cs
@@ -109,15 +109,6 @@ public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
- State(() => WaitingToStart);
- State(() => FailedToStart);
-
- Event(() => Started);
- Event(() => Initialized);
- Event(() => Created);
- Event(() => StartFaulted);
-
Initially(
When(Started)
.Then(instance => { throw new NotSupportedException("This is expected, but nonetheless exceptional"); })
diff --git a/src/MassTransit/MassTransit.AutomatonymousTests/PublishRequest_Specs.cs b/src/MassTransit/MassTransit.AutomatonymousTests/PublishRequest_Specs.cs
index f702dd6..0afc185 100644
--- a/src/MassTransit/MassTransit.AutomatonymousTests/PublishRequest_Specs.cs
+++ b/src/MassTransit/MassTransit.AutomatonymousTests/PublishRequest_Specs.cs
@@ -74,9 +74,6 @@ public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
- Event(() => Started);
-
Initially(
When(Started)
.PublishRequest((instance, context) => new RequestAuthorization
diff --git a/src/MassTransit/MassTransit.AutomatonymousTests/Publish_Specs.cs b/src/MassTransit/MassTransit.AutomatonymousTests/Publish_Specs.cs
index cde0661..4bbab1e 100644
--- a/src/MassTransit/MassTransit.AutomatonymousTests/Publish_Specs.cs
+++ b/src/MassTransit/MassTransit.AutomatonymousTests/Publish_Specs.cs
@@ -75,9 +75,6 @@ public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
- Event(() => Started);
-
Initially(
When(Started)
.Publish((instance, msg) => new StartupComplete
diff --git a/src/MassTransit/MassTransit.AutomatonymousTests/RemoveWhen_Specs.cs b/src/MassTransit/MassTransit.AutomatonymousTests/RemoveWhen_Specs.cs
index 58a23b3..0fd25f2 100644
--- a/src/MassTransit/MassTransit.AutomatonymousTests/RemoveWhen_Specs.cs
+++ b/src/MassTransit/MassTransit.AutomatonymousTests/RemoveWhen_Specs.cs
@@ -101,12 +101,8 @@ class TestStateMachine :
AutomatonymousStateMachine
{
public TestStateMachine()
- {
- InstanceState(x => x.CurrentState);
-
- State(() => Running);
- Event(() => Started);
- Event(() => Stopped);
+ {
+ InstanceState(x => x.CurrentState);
Initially(
When(Started)
diff --git a/src/MassTransit/MassTransit.AutomatonymousTests/Respond_Specs.cs b/src/MassTransit/MassTransit.AutomatonymousTests/Respond_Specs.cs
index b4436ae..175b778 100644
--- a/src/MassTransit/MassTransit.AutomatonymousTests/Respond_Specs.cs
+++ b/src/MassTransit/MassTransit.AutomatonymousTests/Respond_Specs.cs
@@ -75,9 +75,6 @@ public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
- Event(() => Started);
-
Initially(
When(Started)
.Respond(new StartupComplete())
diff --git a/src/MassTransit/MassTransit.AutomatonymousTests/SimpleStateMachine_Specs.cs b/src/MassTransit/MassTransit.AutomatonymousTests/SimpleStateMachine_Specs.cs
index 16e4d24..9f660df 100644
--- a/src/MassTransit/MassTransit.AutomatonymousTests/SimpleStateMachine_Specs.cs
+++ b/src/MassTransit/MassTransit.AutomatonymousTests/SimpleStateMachine_Specs.cs
@@ -100,11 +100,6 @@ public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
- Event(() => Started);
- Event(() => Stopped);
- Event(() => ShouldNotBind);
-
Initially(
When(Started)
.TransitionTo(Running));
@@ -134,4 +129,4 @@ class Stop :
public Guid CorrelationId { get; set; }
}
}
-}
\ No newline at end of file
+}
diff --git a/src/MassTransit/MassTransit.AutomatonymousTests/Testing_Specs.cs b/src/MassTransit/MassTransit.AutomatonymousTests/Testing_Specs.cs
index 92486f3..4b99f83 100644
--- a/src/MassTransit/MassTransit.AutomatonymousTests/Testing_Specs.cs
+++ b/src/MassTransit/MassTransit.AutomatonymousTests/Testing_Specs.cs
@@ -116,11 +116,6 @@ public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
- Event(() => Started);
- Event(() => Stopped);
- Event(() => ShouldNotBind);
-
Initially(
When(Started)
.TransitionTo(Running));
diff --git a/src/MassTransit/MassTransit.AutomatonymousTests/UncorrelatedMessage_Specs.cs b/src/MassTransit/MassTransit.AutomatonymousTests/UncorrelatedMessage_Specs.cs
index 3f153ac..431f702 100644
--- a/src/MassTransit/MassTransit.AutomatonymousTests/UncorrelatedMessage_Specs.cs
+++ b/src/MassTransit/MassTransit.AutomatonymousTests/UncorrelatedMessage_Specs.cs
@@ -110,10 +110,6 @@ public TestStateMachine()
{
InstanceState(x => x.CurrentState);
- State(() => Running);
- Event(() => Started);
- Event(() => CheckStatus);
-
Initially(
When(Started)
.Then((i, d) => i.ServiceName = d.ServiceName)
diff --git a/src/NHibernate.AutomatonymousTests/Vanilla_Specs.cs b/src/NHibernate.AutomatonymousTests/Vanilla_Specs.cs
index 9cf0ccd..7bf324f 100644
--- a/src/NHibernate.AutomatonymousTests/Vanilla_Specs.cs
+++ b/src/NHibernate.AutomatonymousTests/Vanilla_Specs.cs
@@ -176,12 +176,7 @@ public SuperShopper()
{
InstanceState(x => x.CurrentState);
- State(() => OnTheWayToTheStore);
-
- Event(() => ExitFrontDoor);
- Event(() => GotHitByCar);
-
- Event(() => EndOfTheWorld, x => x.Everything, ExitFrontDoor, GotHitByCar);
+ ComposeEvent(EndOfTheWorld, x => x.Everything, ExitFrontDoor, GotHitByCar);
Initially(
When(ExitFrontDoor)