From ed18de016e643e4c42d2e6348e79b0cd9165a49c Mon Sep 17 00:00:00 2001 From: Urs Enzler Date: Wed, 27 Nov 2019 15:17:31 +0100 Subject: [PATCH 1/2] some trials --- .../Appccelerate.StateMachine.Facts.csproj | 2 +- .../Appccelerate.StateMachine.Specs.csproj | 2 +- .../Sync/ActiveStateMachines.cs | 2 +- .../Appccelerate.StateMachine.sln.DotSettings | 1 + .../ActiveStateMachine.cs | 19 ++++++++++++------- .../Appccelerate.StateMachine.csproj | 2 ++ .../AsyncActiveStateMachine.cs | 11 +++++++---- .../ActionHolders/ArgumentActionHolder.cs | 17 +++++++---------- .../AsyncMachine/Events/IFactory.cs | 6 +++++- .../GuardHolders/ArgumentGuardHolder.cs | 10 ++++++---- .../AsyncMachine/StateMachine.cs | 2 +- .../EventInformation.cs | 4 ++-- .../Machine/IExtension.cs | 10 ++++++++-- .../Machine/StateMachine.cs | 2 +- .../NullableExtensionMethods.cs | 16 ++++++++++++++++ 15 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 source/Appccelerate.StateMachine/NullableExtensionMethods.cs diff --git a/source/Appccelerate.StateMachine.Facts/Appccelerate.StateMachine.Facts.csproj b/source/Appccelerate.StateMachine.Facts/Appccelerate.StateMachine.Facts.csproj index a27d89b9..17da7461 100644 --- a/source/Appccelerate.StateMachine.Facts/Appccelerate.StateMachine.Facts.csproj +++ b/source/Appccelerate.StateMachine.Facts/Appccelerate.StateMachine.Facts.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.0 diff --git a/source/Appccelerate.StateMachine.Specs/Appccelerate.StateMachine.Specs.csproj b/source/Appccelerate.StateMachine.Specs/Appccelerate.StateMachine.Specs.csproj index e610038f..9bfc87f1 100644 --- a/source/Appccelerate.StateMachine.Specs/Appccelerate.StateMachine.Specs.csproj +++ b/source/Appccelerate.StateMachine.Specs/Appccelerate.StateMachine.Specs.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.0 diff --git a/source/Appccelerate.StateMachine.Specs/Sync/ActiveStateMachines.cs b/source/Appccelerate.StateMachine.Specs/Sync/ActiveStateMachines.cs index e690cea5..f57c50fb 100644 --- a/source/Appccelerate.StateMachine.Specs/Sync/ActiveStateMachines.cs +++ b/source/Appccelerate.StateMachine.Specs/Sync/ActiveStateMachines.cs @@ -100,7 +100,7 @@ public void EventsQueueing( "when firing an event onto the state machine".x(() => { machine.Fire(FirstEvent); - machine.Fire(SecondEvent); + machine.Fire(SecondEvent, null); machine.Start(); }); diff --git a/source/Appccelerate.StateMachine.sln.DotSettings b/source/Appccelerate.StateMachine.sln.DotSettings index 1cdddc8e..174a38dc 100644 --- a/source/Appccelerate.StateMachine.sln.DotSettings +++ b/source/Appccelerate.StateMachine.sln.DotSettings @@ -1,2 +1,3 @@  + DO_NOT_SHOW <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private, Protected, ProtectedInternal, Internal, Public" Description="Machine.Specifications it"><ElementKinds><Kind Name="Machine.Specifications_Behavior" /><Kind Name="Machine.Specifications_Context" /><Kind Name="Machine.Specifications_ContextBase" /><Kind Name="Machine.Specifications_Specification" /><Kind Name="Machine.Specifications_SupportingField" /><Kind Name="Machine.Specifications_Field" /><Kind Name="Machine.Specifications_Constant" /><Kind Name="Machine.Specifications_Local" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb_aaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy></Policy> \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/ActiveStateMachine.cs b/source/Appccelerate.StateMachine/ActiveStateMachine.cs index 89e4d442..3ed3b655 100644 --- a/source/Appccelerate.StateMachine/ActiveStateMachine.cs +++ b/source/Appccelerate.StateMachine/ActiveStateMachine.cs @@ -43,8 +43,8 @@ public class ActiveStateMachine : private readonly LinkedList> queue; private readonly TState initialState; - private Task worker; - private CancellationTokenSource stopToken; + private Task? worker; + private CancellationTokenSource stopToken = new CancellationTokenSource(); public ActiveStateMachine( StateMachine stateMachine, @@ -116,7 +116,7 @@ public void Fire(TEvent eventId) /// /// The event. /// The event argument. - public void Fire(TEvent eventId, object eventArgument) + public void Fire(TEvent eventId, object? eventArgument) { lock (this.queue) { @@ -141,7 +141,7 @@ public void FirePriority(TEvent eventId) /// /// The event. /// The event argument. - public void FirePriority(TEvent eventId, object eventArgument) + public void FirePriority(TEvent eventId, object? eventArgument) { lock (this.queue) { @@ -260,12 +260,12 @@ public void Stop() try { - this.worker.Wait(); + this.worker?.Wait(); } catch (AggregateException) { // in case the task was stopped before it could actually start, it will be canceled. - if (this.worker.IsFaulted) + if (this.worker?.IsFaulted ?? false) { throw; } @@ -339,7 +339,12 @@ private void ProcessEventQueue(CancellationToken cancellationToken) } } - this.stateMachine.Fire(eventInformation.EventId, eventInformation.EventArgument, this.stateContainer, this.stateContainer, this.stateDefinitions); + this.stateMachine.Fire( + eventInformation.EventId, + eventInformation.EventArgument, + this.stateContainer, + this.stateContainer, + this.stateDefinitions); } } diff --git a/source/Appccelerate.StateMachine/Appccelerate.StateMachine.csproj b/source/Appccelerate.StateMachine/Appccelerate.StateMachine.csproj index 7f17b1db..289a2981 100644 --- a/source/Appccelerate.StateMachine/Appccelerate.StateMachine.csproj +++ b/source/Appccelerate.StateMachine/Appccelerate.StateMachine.csproj @@ -2,6 +2,8 @@ netstandard1.3 + 8 + enable diff --git a/source/Appccelerate.StateMachine/AsyncActiveStateMachine.cs b/source/Appccelerate.StateMachine/AsyncActiveStateMachine.cs index 0bf79a3d..ede6a262 100644 --- a/source/Appccelerate.StateMachine/AsyncActiveStateMachine.cs +++ b/source/Appccelerate.StateMachine/AsyncActiveStateMachine.cs @@ -36,8 +36,8 @@ public class AsyncActiveStateMachine : IAsyncStateMachine> priorityEvents; private readonly TState initialState; - private Task worker; - private CancellationTokenSource stopToken; + private Task? worker; + private CancellationTokenSource stopToken = new CancellationTokenSource(); private TaskCompletionSource workerCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); public AsyncActiveStateMachine( @@ -332,8 +332,11 @@ public async Task Stop() try { - await this.worker - .ConfigureAwait(false); + if (this.worker != null) + { + await this.worker + .ConfigureAwait(false); + } } catch (OperationCanceledException) { diff --git a/source/Appccelerate.StateMachine/AsyncMachine/ActionHolders/ArgumentActionHolder.cs b/source/Appccelerate.StateMachine/AsyncMachine/ActionHolders/ArgumentActionHolder.cs index 540f085f..a4b471ca 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/ActionHolders/ArgumentActionHolder.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/ActionHolders/ArgumentActionHolder.cs @@ -46,17 +46,14 @@ public ArgumentActionHolder(Action action) public async Task Execute(object argument) { - T castArgument = default(T); - - if (argument != Missing.Value && argument != null && !(argument is T)) - { - throw new ArgumentException(ActionHoldersExceptionMessages.CannotCastArgumentToActionArgument(argument, this.Describe())); - } - - if (argument != Missing.Value) + var castArgument = argument switch { - castArgument = (T)argument; - } + T value => value, + _ => throw new ArgumentException( + ActionHoldersExceptionMessages.CannotCastArgumentToActionArgument( + argument, + this.Describe())) + }; await this.action(castArgument).ConfigureAwait(false); } diff --git a/source/Appccelerate.StateMachine/AsyncMachine/Events/IFactory.cs b/source/Appccelerate.StateMachine/AsyncMachine/Events/IFactory.cs index a4c3b24b..4207b770 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/Events/IFactory.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/Events/IFactory.cs @@ -56,7 +56,11 @@ public interface IFactory IGuardHolder CreateGuardHolder(Func guard); - ITransitionContext CreateTransitionContext(IStateDefinition stateDefinition, Missable eventId, object eventArgument, INotifier notifier); + ITransitionContext CreateTransitionContext( + IStateDefinition stateDefinition, + Missable eventId, + object? eventArgument, + INotifier notifier); StateMachineInitializer CreateStateMachineInitializer(IStateDefinition initialState, ITransitionContext context); } diff --git a/source/Appccelerate.StateMachine/AsyncMachine/GuardHolders/ArgumentGuardHolder.cs b/source/Appccelerate.StateMachine/AsyncMachine/GuardHolders/ArgumentGuardHolder.cs index d58ffad1..0224a79f 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/GuardHolders/ArgumentGuardHolder.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/GuardHolders/ArgumentGuardHolder.cs @@ -58,12 +58,14 @@ public ArgumentGuardHolder(Func> guard) /// Result of the guard execution. public async Task Execute(object argument) { - if (argument != null && !(argument is T)) + var castArgument = argument switch { - throw new ArgumentException(GuardHoldersExceptionMessages.CannotCastArgumentToGuardArgument(argument, this.Describe())); - } + T value => value, + _ => throw new ArgumentException( + GuardHoldersExceptionMessages.CannotCastArgumentToGuardArgument(argument, this.Describe())) + }; - return await this.guard((T)argument).ConfigureAwait(false); + return await this.guard(castArgument).ConfigureAwait(false); } /// diff --git a/source/Appccelerate.StateMachine/AsyncMachine/StateMachine.cs b/source/Appccelerate.StateMachine/AsyncMachine/StateMachine.cs index 5aaac00a..57191529 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/StateMachine.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/StateMachine.cs @@ -119,7 +119,7 @@ await stateContainer.ForEach(extension => extension.EnteredInitialState(stateMac /// A representing the asynchronous operation. public async Task Fire( TEvent eventId, - object eventArgument, + object? eventArgument, StateContainer stateContainer, IStateMachineInformation stateMachineInformation, IStateDefinitionDictionary stateDefinitions) diff --git a/source/Appccelerate.StateMachine/EventInformation.cs b/source/Appccelerate.StateMachine/EventInformation.cs index c1e5a76c..98bf2bca 100644 --- a/source/Appccelerate.StateMachine/EventInformation.cs +++ b/source/Appccelerate.StateMachine/EventInformation.cs @@ -27,7 +27,7 @@ namespace Appccelerate.StateMachine public class EventInformation where TEvent : IComparable { - public EventInformation(TEvent eventId, object eventArgument) + public EventInformation(TEvent eventId, object? eventArgument) { this.EventId = eventId; this.EventArgument = eventArgument; @@ -35,6 +35,6 @@ public EventInformation(TEvent eventId, object eventArgument) public TEvent EventId { get; private set; } - public object EventArgument { get; private set; } + public object? EventArgument { get; private set; } } } \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/Machine/IExtension.cs b/source/Appccelerate.StateMachine/Machine/IExtension.cs index 1d7fffbb..1fd4fc94 100644 --- a/source/Appccelerate.StateMachine/Machine/IExtension.cs +++ b/source/Appccelerate.StateMachine/Machine/IExtension.cs @@ -51,7 +51,10 @@ public interface IExtension /// The state machine. /// The event id. /// The event argument. - void EventQueued(IStateMachineInformation stateMachine, TEvent eventId, object eventArgument); + void EventQueued( + IStateMachineInformation stateMachine, + TEvent eventId, + object? eventArgument); /// /// Called after an events was queued with priority. @@ -59,7 +62,10 @@ public interface IExtension /// The state machine. /// The event id. /// The event argument. - void EventQueuedWithPriority(IStateMachineInformation stateMachine, TEvent eventId, object eventArgument); + void EventQueuedWithPriority( + IStateMachineInformation stateMachine, + TEvent eventId, + object? eventArgument); /// /// Called after the state machine switched states. diff --git a/source/Appccelerate.StateMachine/Machine/StateMachine.cs b/source/Appccelerate.StateMachine/Machine/StateMachine.cs index 13aa22d5..cd875b66 100644 --- a/source/Appccelerate.StateMachine/Machine/StateMachine.cs +++ b/source/Appccelerate.StateMachine/Machine/StateMachine.cs @@ -124,7 +124,7 @@ public void Fire( /// The definitions for all states of this state Machine. public void Fire( TEvent eventId, - object eventArgument, + object? eventArgument, StateContainer stateContainer, IStateMachineInformation stateMachineInformation, IStateDefinitionDictionary stateDefinitions) diff --git a/source/Appccelerate.StateMachine/NullableExtensionMethods.cs b/source/Appccelerate.StateMachine/NullableExtensionMethods.cs new file mode 100644 index 00000000..f6278016 --- /dev/null +++ b/source/Appccelerate.StateMachine/NullableExtensionMethods.cs @@ -0,0 +1,16 @@ +namespace Appccelerate.StateMachine +{ + using System; + + public static class NullableExtensionMethods + { + public static TResult? Map( + this T? value, + Func f) + where T : class + where TResult : class + { + return value != null ? f(value) : default; + } + } +} \ No newline at end of file From 199aabc227f68503254b2772c16e1488688fe123 Mon Sep 17 00:00:00 2001 From: Urs Enzler Date: Thu, 12 Dec 2019 17:04:22 +0100 Subject: [PATCH 2/2] Refactored TransitionResult --- .../StateMachineAssertionsExtensionMethods.cs | 9 ++- .../StateMachineAssertionsExtensionMethods.cs | 10 ++- .../AsyncActiveStateMachine.cs | 4 +- .../AsyncMachine/StandardFactory.cs | 2 +- .../AsyncMachine/StateMachine.cs | 5 +- .../AsyncMachine/States/StateLogic.cs | 2 +- ...tionResult.cs => FiredTransitionResult.cs} | 14 ++-- .../Transitions/ITransitionResult.cs | 6 -- .../Transitions/NotFiredTransitionResult.cs | 18 +++++ .../Transitions/TransitionLogic.cs | 4 +- .../AsyncPassiveStateMachine.cs | 4 +- .../Extensions/ExtensionBase.cs | 4 +- .../IAsyncStateMachine.cs | 4 +- .../IStateMachine.cs | 4 +- .../{ => Building}/HierarchyBuilder.cs | 0 .../Machine/{ => Building}/StateBuilder.cs | 0 .../StateMachineDefinitionBuilder.cs | 2 + .../TransitionsExceptionMessages.cs | 0 ...IfNotAvailableStateDefinitionDictionary.cs | 40 ---------- .../Machine/ITransitionDictionary.cs | 42 ---------- .../Machine/ITransitionResult.cs | 6 -- ...IfNotAvailableStateDefinitionDictionary.cs | 51 ------------- .../Machine/StateMachine.cs | 5 +- .../Machine/States/StateLogic.cs | 2 +- ...tionResult.cs => FiredTransitionResult.cs} | 14 ++-- .../Transitions/NotFiredTransitionResult.cs | 18 +++++ .../Machine/Transitions/TransitionInfo.cs | 76 ------------------- .../Machine/Transitions/TransitionLogic.cs | 4 +- .../PassiveStateMachine.cs | 4 +- 29 files changed, 92 insertions(+), 262 deletions(-) rename source/Appccelerate.StateMachine/AsyncMachine/Transitions/{TransitionResult.cs => FiredTransitionResult.cs} (81%) create mode 100644 source/Appccelerate.StateMachine/AsyncMachine/Transitions/NotFiredTransitionResult.cs rename source/Appccelerate.StateMachine/Machine/{ => Building}/HierarchyBuilder.cs (100%) rename source/Appccelerate.StateMachine/Machine/{ => Building}/StateBuilder.cs (100%) rename source/Appccelerate.StateMachine/Machine/{ => Building}/StateMachineDefinitionBuilder.cs (96%) rename source/Appccelerate.StateMachine/Machine/{Transitions => Building}/TransitionsExceptionMessages.cs (100%) delete mode 100644 source/Appccelerate.StateMachine/Machine/IImplicitAddIfNotAvailableStateDefinitionDictionary.cs delete mode 100644 source/Appccelerate.StateMachine/Machine/ITransitionDictionary.cs delete mode 100644 source/Appccelerate.StateMachine/Machine/ImplicitAddIfNotAvailableStateDefinitionDictionary.cs rename source/Appccelerate.StateMachine/Machine/Transitions/{TransitionResult.cs => FiredTransitionResult.cs} (81%) create mode 100644 source/Appccelerate.StateMachine/Machine/Transitions/NotFiredTransitionResult.cs delete mode 100644 source/Appccelerate.StateMachine/Machine/Transitions/TransitionInfo.cs diff --git a/source/Appccelerate.StateMachine.Facts/AsyncMachine/StateMachineAssertionsExtensionMethods.cs b/source/Appccelerate.StateMachine.Facts/AsyncMachine/StateMachineAssertionsExtensionMethods.cs index b0732d22..7f7dee84 100644 --- a/source/Appccelerate.StateMachine.Facts/AsyncMachine/StateMachineAssertionsExtensionMethods.cs +++ b/source/Appccelerate.StateMachine.Facts/AsyncMachine/StateMachineAssertionsExtensionMethods.cs @@ -36,9 +36,12 @@ public static void BeSuccessfulTransitionResultWithNewState(th .ForCondition(transitionResult.Fired) .FailWith("expected successful (fired) transition result."); - Execute.Assertion - .ForCondition(transitionResult.NewState.CompareTo(expectedNewState.Id) == 0) - .FailWith("expected transition result with new state = `" + expectedNewState.Id + "`, but found `" + transitionResult.NewState + "`."); + if (transitionResult is FiredTransitionResult fired) + { + Execute.Assertion + .ForCondition(fired.NewState.CompareTo(expectedNewState.Id) == 0) + .FailWith("expected transition result with new state = `" + expectedNewState.Id + "`, but found `" + fired.NewState + "`."); + } } public static void BeNotFiredTransitionResult(this ObjectAssertions assertions) diff --git a/source/Appccelerate.StateMachine.Facts/StateMachineAssertionsExtensionMethods.cs b/source/Appccelerate.StateMachine.Facts/StateMachineAssertionsExtensionMethods.cs index 56339148..59405766 100644 --- a/source/Appccelerate.StateMachine.Facts/StateMachineAssertionsExtensionMethods.cs +++ b/source/Appccelerate.StateMachine.Facts/StateMachineAssertionsExtensionMethods.cs @@ -19,6 +19,7 @@ namespace Appccelerate.StateMachine.Facts { using System; + using Appccelerate.StateMachine.Machine.Transitions; using FluentAssertions.Execution; using FluentAssertions.Primitives; using StateMachine.Machine; @@ -36,9 +37,12 @@ public static void BeSuccessfulTransitionResultWithNewState(th .ForCondition(transitionResult.Fired) .FailWith("expected successful (fired) transition result."); - Execute.Assertion - .ForCondition(transitionResult.NewState.CompareTo(expectedNewState.Id) == 0) - .FailWith("expected transition result with new state = `" + expectedNewState.Id + "`, but found `" + transitionResult.NewState + "`."); + if (transitionResult is FiredTransitionResult fired) + { + Execute.Assertion + .ForCondition(fired.NewState.CompareTo(expectedNewState.Id) == 0) + .FailWith("expected transition result with new state = `" + expectedNewState.Id + "`, but found `" + fired.NewState + "`."); + } } public static void BeNotFiredTransitionResult(this ObjectAssertions assertions) diff --git a/source/Appccelerate.StateMachine/AsyncActiveStateMachine.cs b/source/Appccelerate.StateMachine/AsyncActiveStateMachine.cs index ede6a262..7c318ed2 100644 --- a/source/Appccelerate.StateMachine/AsyncActiveStateMachine.cs +++ b/source/Appccelerate.StateMachine/AsyncActiveStateMachine.cs @@ -113,7 +113,7 @@ public async Task Fire(TEvent eventId) /// The event. /// The event argument. /// A representing the asynchronous operation. - public async Task Fire(TEvent eventId, object eventArgument) + public async Task Fire(TEvent eventId, object? eventArgument) { this.events.Enqueue(new EventInformation(eventId, eventArgument)); @@ -140,7 +140,7 @@ public async Task FirePriority(TEvent eventId) /// The event. /// The event argument. /// A representing the asynchronous operation. - public async Task FirePriority(TEvent eventId, object eventArgument) + public async Task FirePriority(TEvent eventId, object? eventArgument) { this.priorityEvents.Push(new EventInformation(eventId, eventArgument)); diff --git a/source/Appccelerate.StateMachine/AsyncMachine/StandardFactory.cs b/source/Appccelerate.StateMachine/AsyncMachine/StandardFactory.cs index 8781eacb..26932800 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/StandardFactory.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/StandardFactory.cs @@ -107,7 +107,7 @@ public virtual IGuardHolder CreateGuardHolder(Func> guard) return new ArgumentGuardHolder(guard); } - public virtual ITransitionContext CreateTransitionContext(IStateDefinition state, Missable eventId, object eventArgument, INotifier notifier) + public virtual ITransitionContext CreateTransitionContext(IStateDefinition state, Missable eventId, object? eventArgument, INotifier notifier) { return new TransitionContext(state, eventId, eventArgument, notifier); } diff --git a/source/Appccelerate.StateMachine/AsyncMachine/StateMachine.cs b/source/Appccelerate.StateMachine/AsyncMachine/StateMachine.cs index 57191529..e1b5edb2 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/StateMachine.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/StateMachine.cs @@ -23,6 +23,7 @@ namespace Appccelerate.StateMachine.AsyncMachine using Events; using Infrastructure; using States; + using Transitions; /// /// Base implementation of a state machine. @@ -134,13 +135,13 @@ await stateContainer.ForEach(extension => extension.FiringEvent(stateMachineInfo var result = await this.stateLogic.Fire(currentState, context, stateContainer) .ConfigureAwait(false); - if (!result.Fired) + if (!(result is FiredTransitionResult firedTransitionResult)) { this.OnTransitionDeclined(context); return; } - var newState = stateDefinitions[result.NewState]; + var newState = stateDefinitions[firedTransitionResult.NewState]; await SwitchStateTo(newState, stateContainer, stateMachineInformation) .ConfigureAwait(false); diff --git a/source/Appccelerate.StateMachine/AsyncMachine/States/StateLogic.cs b/source/Appccelerate.StateMachine/AsyncMachine/States/StateLogic.cs index 5b3c3c07..4ddb9c0b 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/States/StateLogic.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/States/StateLogic.cs @@ -56,7 +56,7 @@ public async Task> Fire( { Guard.AgainstNullArgument("context", context); - var result = TransitionResult.NotFired; + ITransitionResult result = new NotFiredTransitionResult(); if (stateDefinition.Transitions.TryGetValue(context.EventId.Value, out var transitionsForEvent)) { diff --git a/source/Appccelerate.StateMachine/AsyncMachine/Transitions/TransitionResult.cs b/source/Appccelerate.StateMachine/AsyncMachine/Transitions/FiredTransitionResult.cs similarity index 81% rename from source/Appccelerate.StateMachine/AsyncMachine/Transitions/TransitionResult.cs rename to source/Appccelerate.StateMachine/AsyncMachine/Transitions/FiredTransitionResult.cs index 2f35eb34..7a1f49ef 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/Transitions/TransitionResult.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/Transitions/FiredTransitionResult.cs @@ -20,15 +20,17 @@ namespace Appccelerate.StateMachine.AsyncMachine.Transitions { using System; - public class TransitionResult + /// + /// Represents a fired transition. + /// + /// ype of the states. + public class FiredTransitionResult : ITransitionResult where TState : IComparable { - public static readonly ITransitionResult NotFired = new TransitionResult(false, default(TState)); - - public TransitionResult(bool fired, TState newState) + public FiredTransitionResult( + TState newState) { - this.Fired = fired; this.NewState = newState; } @@ -36,7 +38,7 @@ public TransitionResult(bool fired, TState newState) /// Gets a value indicating whether this is fired. /// /// true if fired; otherwise, false. - public bool Fired { get; } + public bool Fired => true; /// /// Gets the new state the state machine is in. diff --git a/source/Appccelerate.StateMachine/AsyncMachine/Transitions/ITransitionResult.cs b/source/Appccelerate.StateMachine/AsyncMachine/Transitions/ITransitionResult.cs index 9370f0c3..be18486a 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/Transitions/ITransitionResult.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/Transitions/ITransitionResult.cs @@ -32,11 +32,5 @@ public interface ITransitionResult /// /// true if fired; otherwise, false. bool Fired { get; } - - /// - /// Gets the new state. - /// - /// The new state. - TState NewState { get; } } } \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/AsyncMachine/Transitions/NotFiredTransitionResult.cs b/source/Appccelerate.StateMachine/AsyncMachine/Transitions/NotFiredTransitionResult.cs new file mode 100644 index 00000000..e4e72851 --- /dev/null +++ b/source/Appccelerate.StateMachine/AsyncMachine/Transitions/NotFiredTransitionResult.cs @@ -0,0 +1,18 @@ +namespace Appccelerate.StateMachine.AsyncMachine.Transitions +{ + using System; + + /// + /// Represents a not fired transition - there was no transition found for an event in the current state or a super state. + /// + /// ype of the states. + public class NotFiredTransitionResult : ITransitionResult + where TState : IComparable + { + /// + /// Gets a value indicating whether this is fired. + /// + /// true if fired; otherwise, false. + public bool Fired => false; + } +} \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/AsyncMachine/Transitions/TransitionLogic.cs b/source/Appccelerate.StateMachine/AsyncMachine/Transitions/TransitionLogic.cs index 6e85e0d9..de318fc9 100644 --- a/source/Appccelerate.StateMachine/AsyncMachine/Transitions/TransitionLogic.cs +++ b/source/Appccelerate.StateMachine/AsyncMachine/Transitions/TransitionLogic.cs @@ -62,7 +62,7 @@ await this.extensionHost context)) .ConfigureAwait(false); - return TransitionResult.NotFired; + return new NotFiredTransitionResult(); } context.OnTransitionBegin(); @@ -98,7 +98,7 @@ await this.extensionHost context)) .ConfigureAwait(false); - return new TransitionResult(true, newState); + return new FiredTransitionResult(newState); } private static void HandleException(Exception exception, ITransitionContext context) diff --git a/source/Appccelerate.StateMachine/AsyncPassiveStateMachine.cs b/source/Appccelerate.StateMachine/AsyncPassiveStateMachine.cs index 1f9c1b08..8cf14702 100644 --- a/source/Appccelerate.StateMachine/AsyncPassiveStateMachine.cs +++ b/source/Appccelerate.StateMachine/AsyncPassiveStateMachine.cs @@ -116,7 +116,7 @@ public async Task Fire(TEvent eventId) /// The event. /// The event argument. /// A representing the asynchronous operation. - public async Task Fire(TEvent eventId, object eventArgument) + public async Task Fire(TEvent eventId, object? eventArgument) { this.events.Enqueue(new EventInformation(eventId, eventArgument)); @@ -143,7 +143,7 @@ public async Task FirePriority(TEvent eventId) /// The event. /// The event argument. /// A representing the asynchronous operation. - public async Task FirePriority(TEvent eventId, object eventArgument) + public async Task FirePriority(TEvent eventId, object? eventArgument) { this.priorityEvents.Push(new EventInformation(eventId, eventArgument)); diff --git a/source/Appccelerate.StateMachine/Extensions/ExtensionBase.cs b/source/Appccelerate.StateMachine/Extensions/ExtensionBase.cs index d4a6f040..43769d61 100644 --- a/source/Appccelerate.StateMachine/Extensions/ExtensionBase.cs +++ b/source/Appccelerate.StateMachine/Extensions/ExtensionBase.cs @@ -56,7 +56,7 @@ public virtual void StoppedStateMachine(IStateMachineInformation /// The state machine. /// The event id. /// The event argument. - public virtual void EventQueued(IStateMachineInformation stateMachine, TEvent eventId, object eventArgument) + public virtual void EventQueued(IStateMachineInformation stateMachine, TEvent eventId, object? eventArgument) { } @@ -66,7 +66,7 @@ public virtual void EventQueued(IStateMachineInformation stateMa /// The state machine. /// The event id. /// The event argument. - public virtual void EventQueuedWithPriority(IStateMachineInformation stateMachine, TEvent eventId, object eventArgument) + public virtual void EventQueuedWithPriority(IStateMachineInformation stateMachine, TEvent eventId, object? eventArgument) { } diff --git a/source/Appccelerate.StateMachine/IAsyncStateMachine.cs b/source/Appccelerate.StateMachine/IAsyncStateMachine.cs index f911c281..f96fdfc6 100644 --- a/source/Appccelerate.StateMachine/IAsyncStateMachine.cs +++ b/source/Appccelerate.StateMachine/IAsyncStateMachine.cs @@ -72,7 +72,7 @@ public interface IAsyncStateMachine /// The event. /// The event argument. /// A representing the asynchronous operation. - Task Fire(TEvent eventId, object eventArgument); + Task Fire(TEvent eventId, object? eventArgument); /// /// Fires the specified priority event. The event will be handled before any already queued event. @@ -87,7 +87,7 @@ public interface IAsyncStateMachine /// The event. /// The event argument. /// A representing the asynchronous operation. - Task FirePriority(TEvent eventId, object eventArgument); + Task FirePriority(TEvent eventId, object? eventArgument); /// /// Starts the state machine. Events will be processed. diff --git a/source/Appccelerate.StateMachine/IStateMachine.cs b/source/Appccelerate.StateMachine/IStateMachine.cs index b0f4b4b9..12e3281a 100644 --- a/source/Appccelerate.StateMachine/IStateMachine.cs +++ b/source/Appccelerate.StateMachine/IStateMachine.cs @@ -70,7 +70,7 @@ public interface IStateMachine /// /// The event. /// The event argument. - void Fire(TEvent eventId, object eventArgument); + void Fire(TEvent eventId, object? eventArgument); /// /// Fires the specified priority event. The event will be handled before any already queued event. @@ -83,7 +83,7 @@ public interface IStateMachine /// /// The event. /// The event argument. - void FirePriority(TEvent eventId, object eventArgument); + void FirePriority(TEvent eventId, object? eventArgument); /// /// Starts the state machine. Events will be processed. diff --git a/source/Appccelerate.StateMachine/Machine/HierarchyBuilder.cs b/source/Appccelerate.StateMachine/Machine/Building/HierarchyBuilder.cs similarity index 100% rename from source/Appccelerate.StateMachine/Machine/HierarchyBuilder.cs rename to source/Appccelerate.StateMachine/Machine/Building/HierarchyBuilder.cs diff --git a/source/Appccelerate.StateMachine/Machine/StateBuilder.cs b/source/Appccelerate.StateMachine/Machine/Building/StateBuilder.cs similarity index 100% rename from source/Appccelerate.StateMachine/Machine/StateBuilder.cs rename to source/Appccelerate.StateMachine/Machine/Building/StateBuilder.cs diff --git a/source/Appccelerate.StateMachine/Machine/StateMachineDefinitionBuilder.cs b/source/Appccelerate.StateMachine/Machine/Building/StateMachineDefinitionBuilder.cs similarity index 96% rename from source/Appccelerate.StateMachine/Machine/StateMachineDefinitionBuilder.cs rename to source/Appccelerate.StateMachine/Machine/Building/StateMachineDefinitionBuilder.cs index e3051069..6870e15e 100644 --- a/source/Appccelerate.StateMachine/Machine/StateMachineDefinitionBuilder.cs +++ b/source/Appccelerate.StateMachine/Machine/Building/StateMachineDefinitionBuilder.cs @@ -16,6 +16,8 @@ // //------------------------------------------------------------------------------- +using Appccelerate.StateMachine.Machine.Building; + namespace Appccelerate.StateMachine.Machine { using System; diff --git a/source/Appccelerate.StateMachine/Machine/Transitions/TransitionsExceptionMessages.cs b/source/Appccelerate.StateMachine/Machine/Building/TransitionsExceptionMessages.cs similarity index 100% rename from source/Appccelerate.StateMachine/Machine/Transitions/TransitionsExceptionMessages.cs rename to source/Appccelerate.StateMachine/Machine/Building/TransitionsExceptionMessages.cs diff --git a/source/Appccelerate.StateMachine/Machine/IImplicitAddIfNotAvailableStateDefinitionDictionary.cs b/source/Appccelerate.StateMachine/Machine/IImplicitAddIfNotAvailableStateDefinitionDictionary.cs deleted file mode 100644 index 87c90569..00000000 --- a/source/Appccelerate.StateMachine/Machine/IImplicitAddIfNotAvailableStateDefinitionDictionary.cs +++ /dev/null @@ -1,40 +0,0 @@ -//------------------------------------------------------------------------------- -// -// Copyright (c) 2008-2019 Appccelerate -// -// 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 Appccelerate.StateMachine.Machine -{ - using System; - using States; - - public interface IImplicitAddIfNotAvailableStateDefinitionDictionary - where TState : IComparable - where TEvent : IComparable - { - /// - /// Gets the with the specified state id. - /// If there exists no StateDefinition for the stateId, a new one is implicitly created, added and returned. - /// - /// State with the specified id. - /// The State id. - /// The State with the specified id. - StateDefinition this[TState stateId] - { - get; - } - } -} \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/Machine/ITransitionDictionary.cs b/source/Appccelerate.StateMachine/Machine/ITransitionDictionary.cs deleted file mode 100644 index d12876ea..00000000 --- a/source/Appccelerate.StateMachine/Machine/ITransitionDictionary.cs +++ /dev/null @@ -1,42 +0,0 @@ -//------------------------------------------------------------------------------- -// -// Copyright (c) 2008-2019 Appccelerate -// -// 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 Appccelerate.StateMachine.Machine -{ - using System; - using System.Collections.Generic; - using Transitions; - - public interface ITransitionDictionary - where TState : IComparable - where TEvent : IComparable - { - /// - /// Adds the specified event id. - /// - /// The event id. - /// The transition. - void Add(TEvent eventId, TransitionDefinition transitionDefinition); - - /// - /// Gets all transitions. - /// - /// All transitions. - IEnumerable> GetTransitions(); - } -} \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/Machine/ITransitionResult.cs b/source/Appccelerate.StateMachine/Machine/ITransitionResult.cs index c1674535..1210230c 100644 --- a/source/Appccelerate.StateMachine/Machine/ITransitionResult.cs +++ b/source/Appccelerate.StateMachine/Machine/ITransitionResult.cs @@ -32,11 +32,5 @@ public interface ITransitionResult /// /// true if fired; otherwise, false. bool Fired { get; } - - /// - /// Gets the new state. - /// - /// The new state. - TState NewState { get; } } } \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/Machine/ImplicitAddIfNotAvailableStateDefinitionDictionary.cs b/source/Appccelerate.StateMachine/Machine/ImplicitAddIfNotAvailableStateDefinitionDictionary.cs deleted file mode 100644 index d9bf7e64..00000000 --- a/source/Appccelerate.StateMachine/Machine/ImplicitAddIfNotAvailableStateDefinitionDictionary.cs +++ /dev/null @@ -1,51 +0,0 @@ -//------------------------------------------------------------------------------- -// -// Copyright (c) 2008-2019 Appccelerate -// -// 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 Appccelerate.StateMachine.Machine -{ - using System; - using System.Collections.Generic; - using System.Linq; - using States; - - public class ImplicitAddIfNotAvailableStateDefinitionDictionary : IImplicitAddIfNotAvailableStateDefinitionDictionary - where TState : IComparable - where TEvent : IComparable - { - private readonly Dictionary> dictionary = new Dictionary>(); - - public StateDefinition this[TState stateId] - { - get - { - if (!this.dictionary.ContainsKey(stateId)) - { - this.dictionary.Add(stateId, new StateDefinition(stateId)); - } - - return this.dictionary[stateId]; - } - } - - public IReadOnlyDictionary> ReadOnlyDictionary => - this.dictionary - .ToDictionary( - pair => pair.Key, - pair => (IStateDefinition)pair.Value); - } -} \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/Machine/StateMachine.cs b/source/Appccelerate.StateMachine/Machine/StateMachine.cs index cd875b66..12600207 100644 --- a/source/Appccelerate.StateMachine/Machine/StateMachine.cs +++ b/source/Appccelerate.StateMachine/Machine/StateMachine.cs @@ -19,6 +19,7 @@ namespace Appccelerate.StateMachine.Machine { using System; + using Appccelerate.StateMachine.Machine.Transitions; using Events; using Infrastructure; using States; @@ -137,13 +138,13 @@ public void Fire( var context = this.factory.CreateTransitionContext(currentState, new Missable(eventId), eventArgument, this); var result = this.stateLogic.Fire(currentState, context, stateContainer); - if (!result.Fired) + if (!(result is FiredTransitionResult firedTransitionResult)) { this.OnTransitionDeclined(context); return; } - var newState = stateDefinitions[result.NewState]; + var newState = stateDefinitions[firedTransitionResult.NewState]; SwitchStateTo(newState, stateContainer, stateMachineInformation); stateContainer.ForEach(extension => extension.FiredEvent(stateMachineInformation, context)); diff --git a/source/Appccelerate.StateMachine/Machine/States/StateLogic.cs b/source/Appccelerate.StateMachine/Machine/States/StateLogic.cs index fced4c01..518f5f7d 100644 --- a/source/Appccelerate.StateMachine/Machine/States/StateLogic.cs +++ b/source/Appccelerate.StateMachine/Machine/States/StateLogic.cs @@ -55,7 +55,7 @@ public ITransitionResult Fire( { Guard.AgainstNullArgument("context", context); - var result = TransitionResult.NotFired; + ITransitionResult result = new NotFiredTransitionResult(); if (stateDefinition.Transitions.TryGetValue(context.EventId.Value, out var transitionsForEvent)) { diff --git a/source/Appccelerate.StateMachine/Machine/Transitions/TransitionResult.cs b/source/Appccelerate.StateMachine/Machine/Transitions/FiredTransitionResult.cs similarity index 81% rename from source/Appccelerate.StateMachine/Machine/Transitions/TransitionResult.cs rename to source/Appccelerate.StateMachine/Machine/Transitions/FiredTransitionResult.cs index 1836e0d1..0fffd8f2 100644 --- a/source/Appccelerate.StateMachine/Machine/Transitions/TransitionResult.cs +++ b/source/Appccelerate.StateMachine/Machine/Transitions/FiredTransitionResult.cs @@ -20,15 +20,17 @@ namespace Appccelerate.StateMachine.Machine.Transitions { using System; - public class TransitionResult + /// + /// Represents a fired transition. + /// + /// ype of the states. + public class FiredTransitionResult : ITransitionResult where TState : IComparable { - public static readonly ITransitionResult NotFired = new TransitionResult(false, default(TState)); - - public TransitionResult(bool fired, TState newState) + public FiredTransitionResult( + TState newState) { - this.Fired = fired; this.NewState = newState; } @@ -36,7 +38,7 @@ public TransitionResult(bool fired, TState newState) /// Gets a value indicating whether this is fired. /// /// true if fired; otherwise, false. - public bool Fired { get; } + public bool Fired => true; /// /// Gets the new state the state machine is in. diff --git a/source/Appccelerate.StateMachine/Machine/Transitions/NotFiredTransitionResult.cs b/source/Appccelerate.StateMachine/Machine/Transitions/NotFiredTransitionResult.cs new file mode 100644 index 00000000..3d116407 --- /dev/null +++ b/source/Appccelerate.StateMachine/Machine/Transitions/NotFiredTransitionResult.cs @@ -0,0 +1,18 @@ +namespace Appccelerate.StateMachine.Machine.Transitions +{ + using System; + + /// + /// Represents a not fired transition - there was no transition found for an event in the current state or a super state. + /// + /// ype of the states. + public class NotFiredTransitionResult : ITransitionResult + where TState : IComparable + { + /// + /// Gets a value indicating whether this is fired. + /// + /// true if fired; otherwise, false. + public bool Fired => false; + } +} \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/Machine/Transitions/TransitionInfo.cs b/source/Appccelerate.StateMachine/Machine/Transitions/TransitionInfo.cs deleted file mode 100644 index d7baf7e0..00000000 --- a/source/Appccelerate.StateMachine/Machine/Transitions/TransitionInfo.cs +++ /dev/null @@ -1,76 +0,0 @@ -//------------------------------------------------------------------------------- -// -// Copyright (c) 2008-2019 Appccelerate -// -// 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 Appccelerate.StateMachine.Machine.Transitions -{ - using System; - using System.Collections.Generic; - - using ActionHolders; - using GuardHolders; - using States; - - /// - /// Describes a transition. - /// - /// Type fo the states. - /// Type of the events. - public class TransitionInfo - where TState : IComparable - where TEvent : IComparable - { - public TransitionInfo(TEvent eventId, IStateDefinition source, IStateDefinition target, IGuardHolder guard, IEnumerable actions) - { - this.EventId = eventId; - this.Source = source; - this.Target = target; - this.Guard = guard; - this.Actions = actions; - } - - /// - /// Gets the event id. - /// - /// The event id. - public TEvent EventId { get; } - - /// - /// Gets the source. - /// - /// The source. - public IStateDefinition Source { get; } - - /// - /// Gets the target. - /// - /// The target. - public IStateDefinition Target { get; } - - /// - /// Gets the guard. - /// - /// The guard. - public IGuardHolder Guard { get; } - - /// - /// Gets the actions. - /// - /// The actions. - public IEnumerable Actions { get; } - } -} \ No newline at end of file diff --git a/source/Appccelerate.StateMachine/Machine/Transitions/TransitionLogic.cs b/source/Appccelerate.StateMachine/Machine/Transitions/TransitionLogic.cs index 3f01037f..11cf07d6 100644 --- a/source/Appccelerate.StateMachine/Machine/Transitions/TransitionLogic.cs +++ b/source/Appccelerate.StateMachine/Machine/Transitions/TransitionLogic.cs @@ -58,7 +58,7 @@ public ITransitionResult Fire( transitionDefinition, context)); - return TransitionResult.NotFired; + return new NotFiredTransitionResult(); } context.OnTransitionBegin(); @@ -88,7 +88,7 @@ public ITransitionResult Fire( transitionDefinition, context)); - return new TransitionResult(true, newState); + return new FiredTransitionResult(newState); } private static void HandleException(Exception exception, ITransitionContext context) diff --git a/source/Appccelerate.StateMachine/PassiveStateMachine.cs b/source/Appccelerate.StateMachine/PassiveStateMachine.cs index 93231871..2a93d45d 100644 --- a/source/Appccelerate.StateMachine/PassiveStateMachine.cs +++ b/source/Appccelerate.StateMachine/PassiveStateMachine.cs @@ -129,7 +129,7 @@ public void Fire(TEvent eventId) /// /// The event. /// The event argument. - public void Fire(TEvent eventId, object eventArgument) + public void Fire(TEvent eventId, object? eventArgument) { this.events.AddLast(new EventInformation(eventId, eventArgument)); @@ -152,7 +152,7 @@ public void FirePriority(TEvent eventId) /// /// The event. /// The event argument. - public void FirePriority(TEvent eventId, object eventArgument) + public void FirePriority(TEvent eventId, object? eventArgument) { this.events.AddFirst(new EventInformation(eventId, eventArgument));