dotnet-state-machine / stateless Goto Github PK
View Code? Open in Web Editor NEWA simple library for creating state machines in C# code
License: Other
A simple library for creating state machines in C# code
License: Other
How can errors be handled during state transition? Say, an error caused during OnEntry, or OnExit which shouldn't be causing the state change.
It would be nice if the default exception thrown when a trigger is valid for a given state but a guard condition is not met mentioned the guard description text.
Somewhat related to #54
In this case VS 2013
I really have trouble figuring out why a project as excellent, and interesting, as this one doesn't provide a clear statement about what is required to use it ... a simple statement. Do you really want new users to be frustrated figuring out why it won't compile ... why the 'nameof operator doesn't exist ?
I am able to use NuGet to install it in VS 2013, but then I have to use ReSharper's reflection tools to look at the source.
I'd appreciate one clean package that does not target SilverLight, or Win Mobile that I can add to Visual Studio.
thanks, Bill
Solution is VS 2012 but the project uses C# 6.0 (nameof etc.) and requires VS2015. Please update solution file to 2015 format to clarify what is really needed to build or stay with older compatible syntax that enables build with 2012.
Personally, I use 2013 and 2015. With the free available Express Editions there seems to be not much benefit with having an old 2012 Solution file (that does not build in 2012 or 2013).
In my opinion the state machine should not receive the initial state in the constructor.
This makes it almost impossible (at least cumbersome and unclean) to use it with a dependency injection container. The state machine should be initialized with fsm.Initialize(initialState)
for example:
i have 3 states: A B C and A,B can go state C...so when i in OnEnterC() how can i know the source is A or B?
very thanks....
Hello,
Maybe I'm just missing something simple/obvious in my wiring, but I'm struggling to figure out how this should be implemented.
The short version of my question: is there a way to call Fire()
on parameterized triggers without having to store a reference to SetTriggerParameters
and passing it around? Or am I missing something fundamental and going about it the wrong way?
The long version of my question...
the implementation in the readme does the following in the config:
var assignTrigger = stateMachine.SetTriggerParameters<string>(Trigger.Assign);
stateMachine.Configure(State.Assigned)
.OnEntryFrom(assignTrigger, email => OnAssigned(email));
and then immediately calls .Fire(assignTrigger, "[email protected]")
. Note the immediate use of assignTrigger
. However, how is this expected to work when the call to .Fire()
comes elsewhere, like in a domain object?
private void MyMethod_OnDomainObject(){
_machine.Fire( ___what goes here?___, "[email protected]");
}
what should be the first argument? It doesn't seem right that I would have to store assignTrigger as a class property somewhere. This is what's done in the bug tracker example:
public Bug(string title)
{
// ...
_assignTrigger = _machine.SetTriggerParameters<string>(Trigger.Assign);
// ....
}
but seems like it might quickly get out of hand when you have multiple parameterized triggers.
I took a look at the source and I see that there are methods such as this overload of Fire():
public void Fire<TArg0>(TriggerWithParameters<TArg0> trigger, TArg0 arg0) { // snipped }
I've tried multiple variations of calling this from my domain object to no avail, so maybe I'm just goofing up my generics / etc? Such as calling _machine.Fire<string>();
and trying to pass in an argument that matches the StateMachine<State,Event>.TriggerWithParameters<string> trigger, string arg0
signature. Can this be done? Or am I missing something fundamental and going about it the wrong way?
Hello all, long time user of Stateless and first time poster!
Disclaimer: I am not very experienced with C# and taught myself programing through a lot of trial and error, apologies in advance for disturbing you f^^;)...
My states are classes deriving from a simple BaseState I made:
https://gist.github.com/arun02139/d34e70e3b4ac9441a8af
Sometimes I want to check the state of a machine but I have to do so by checking the state type against the type of the current State using a custom function I added . Is there a more elegant way to do this when I don't want the state classes themselves to be exposed outside of the 'Battle' class that maintains the state-machine?
Thanks for your time and thoughts, everyone!
Hi,
is there a possibility to force the state machine to switch into certain state? E.g. if I have undo functionality in my application it could be necessary to set a certain state after an undo command.
Is it possible to use ToDotGraph() to generate dynamic information about a running state machine ? For instance, would it be possible to visualize and actualize dynamically the actual and the previous state ?
I have a parametrized trigger, and in most cases, i would like to ignore it, unless it happens with some specific parameter values. How to properly achieve this? The guard expressions in 'If' methods do not receive trigger parameters.
The only way it seems, is to do PermitDynamic, and return the current state if you want to ignore the trigger?
Thanks
The existing documentation
var stateMachine = new StateMachine<State, Trigger>(
() => myState.Value,
s => myState.Value = s);
doesn't really illustrate how one might use an actual ORM (Like EF) to persist the StateMachine to storage for long-lived processes or ones that live in transient processes.
Does the ORM-mapped object extend StateMachine? Does it have a StateMachine? How do you really wire up the materialization & saving beyond the conceptual example?
Any chance we can get a better example of the intended usage?
Thanks,
Paul
Please add a means to specify the default sub state when defining hierarchical states.
There is following OnEntryFrom() overload :
public StateConfiguration OnEntryFrom<TArg0>(TriggerWithParameters<TArg0> trigger, Action<TArg0> entryAction, string entryActionDescription = null);
For InternalTransition() the closest we currently have is :
public StateConfiguration InternalTransition<TArg0>(TriggerWithParameters<TArg0> trigger, Action<TArg0, Transition> entryAction)
Ddifference is in action argument :
Action<TArg0, Transition> entryAction
Action<TArg0> entryAction
.Would be nice to have same overload for InternalTransition() so I we can switch actions from OnEntryFrom() to InternalTransitions() without need to change the action signature by adding Transition argument.
PS. Perhaps we could have same set of overloads for both methods?
We would like to extend Stateless to support multiple concurrent states. For example, AcceptPayment should transition to both SendConfirmationEmail and OrderFromFactory. We plan to start out by make TState into List and go from there. Has anybody tried this yet? Thx! allan
thank you for this project. if possible , attach one example like BlogPost with asp.net mvc and EF .
stateMachine.Configure("a").onEntry( id => OnEntryWithID(id) )
private void OnEntryWithID(int id)
{
Console.Write("id={0}",id);
}
stateMachine.Fire("a", 1111);
very thanks!!!!!!!!!!!!!!!!!!
Hi,
I have one question. When we have scenario like there are parent child stateless machines, can we allow child trigger to make transition in parent machine.
How can we build parent child stateless machines
Given PermitIf takes a Boolean guard clause, it would be useful to have a PermitIfElse function:
PermitIfElse(trigger, stateIfTrue, stateIfFalse, Func guard)
Would an upgrade to new standards be a good idea at this point or wait for v2.
I have a unit test that expects InvalidOperationException to throw when attempting to fire in a state where that trigger is not allowed. Was working fine until I updated from 2.5.62. The exception is throwing on the call to ResourceManager.GetString(name, cultureInfo).
Assert.Throws() Failure
Expected: typeof(System.InvalidOperationException)
Actual: typeof(System.Resources.MissingManifestResourceException): Unable to load resources for resource file "Stateless.StateMachineResources" in package "8c4135be-e11e-423c-829b-76933c7da27f".
Now that .NET Core is out Stateless makes sense as a project that targets .NET core
Hi,
We need a separate stateless and our domain objects. Created a new sample project for dependency injection. Can you please consider dependency injection support.
https://github.com/omerfarukz/statelessDependencyInjectionSample
Regards
I downloaded Stateless from Nuget just yesterday, and I need the PermitDynamic function with more arguments.
In my project, reflection doesn't work for more than one argument. Anyway, in the test units I tried to make a new one with two arguments, and it works! That's because the test units come from GIT, and that issue has been fixed just two weeks ago.
Looking for some information about Nuget versioning, I found out that in the AssemblyInfo file (in the Properties subfolder) there is an older version (2.4) than the one on the Nuget repository (2.5.29), so I think I got an old version of the library in my project.
Thank you.
It would be great to have the possibility to create a report (state diagram) of the state machine. When you create a yEd (http://www.yworks.com/en/products/yfiles/yed/) file, it's simple to visualize it.
I have used the latest version of Stateless (2.5.11) in a recent project. It worked fine on my development machine.
I ran into issues when I deployed to a UAT test machine.
I get the following error message whenever I call the CanFire method on the StateMachine:
System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.IO.FileLoadException: Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047) File name: 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes'
at Stateless.StateMachine2.StateRepresentation.TryFindLocalHandler(TTrigger trigger, TriggerBehaviour& handler) at Stateless.StateMachine
2.StateRepresentation.TryFindHandler(TTrigger trigger, TriggerBehaviour& handler)
at Stateless.StateMachine`2.CanFire(TTrigger trigger)
at Company.MyProject.Entities.Models.Form.TryUpdateStatus(FormTriggers trigger) in ...
The only way I was able to get around this was to install the Nuget package "Stateless for .NET 4.0" (https://www.nuget.org/packages/stateless-4.0/).
It would be nice if the changes made in that clone could be incorporated into the official stateless project so that stateless works properly in .NET 4.
I recently started using Stateless and have found it to be extremely useful! Thank you!
My question is about compound state transitions. I am using Stateless to model workflow, and late in the workflow I am required to know whether the machine traversed one path or another. Is there a way look back to where the state machine has been? I would prefer to not have to externally record my own "Fire" invocations, because that would force me to keep additional state variables, which Stateless has so far been great at helping me avoid. What is the "correct" way of keeping track of multiple transitions?
First of all forgive me, this isnt an issue but rather a general question. (and if its been asked, apologize about that as well)
I'd like to provide a bit of external config... eg, let users define states etc. Does stateless support definition and/or states from something other than an enum?
I dont mind writing something that initializes the container the proper way etc, but I cant really easily generate enums on the fly.
This means that you can store a complete entity within the machine and make it available to any transitions. The accessor and mutator can still be use to point to a property within the context. Not necessarily an issue - but what do you think?
Please, consider running the following code:
class Program
{
public enum Page
{
ChooseLanguage,
ProductList,
Quantity
}
public enum Trigger
{
Back,
Forward
}
static void Main(string[] args)
{
var retail = new StateMachine<Page, Trigger>(Page.ChooseLanguage);
retail.Configure(Page.ChooseLanguage)
.Permit(Trigger.Forward, Page.ProductList)
.OnExit(Log);
retail.Configure(Page.ProductList)
.Permit(Trigger.Back, Page.ChooseLanguage)
.OnExit(Log);
retail.Configure(Page.ProductList)
.Permit(Trigger.Forward, Page.Quantity)
.OnExit(Log);
retail.Configure(Page.Quantity)
.Permit(Trigger.Back, Page.ProductList)
.OnExit(Log);
while (retail.CanFire(Trigger.Forward))
{
retail.Fire(Trigger.Forward);
}
}
static void Log(StateMachine<Page, Trigger>.Transition transition)
{
Console.WriteLine("{0} -> {1}, Trigger: {2}", transition.Source, transition.Destination, transition.Trigger);
}
}
It'll give you the following output:
ChooseLanguage -> ProductList, Trigger: Forward
ProductList -> Quantity, Trigger: Forward
ProductList -> Quantity, Trigger: Forward
Thanks.
Hello!
I have found it useful to be able to visualize the state configuration of state machines on runtime. With this approach the code is the authoritative source and state diagrams a by-product and therefore always up to date.
I have made a proof of concept which you can see at nblumhardt/stateless@master...tlk:stringformatter
The idea is to make it possible for library users to implement the IStringFormatter interface and pass a custom formatter object to StateMachine.ToString which will then return a custom string representation of the state machine.
In the test code there is a DotGraphFormatter implementation which generates output in the DOT graph language.
Example output from DotGraphFormatter:
digraph {
A -> B [label="X"];
A -> C [label="Y [IsTrue]"];
}
This can then be processed by https://github.com/ellson/graphviz/ or other tools that support the DOT graph language, e.g. http://www.webgraphviz.com
Ideas or suggestions on better approaches are most welcome!
Would you be interested in making the Stateless library support something like this?
Best regards,
Thomas
Async tasks are currently fired, and forgotten. Things can get mangled up easily. An AsyncState machine requires three behaviors:
Thoughts?
Hi All,
First many thanks for this amazing library. I have been using it in many projects for the past 2 years, it's been very helpful.
I have however a small concern about a feature which seems to be missing, with regards to UML 2 state machines specifications.
No action can be attached to an event. There is no possibility to execute an action on a Fire itself.
The only way to achieve that today would be to create a Parameterised Triggers and then to execute the attached function on an EntryFrom.
But this does not cover all the cases.
Let's take the example below :
In this example, the machine is deterministic, but depending on when and from where the event T1 is raise the associated action is not the same.
I though it would be amazing to configure a State mahcine like this:
stateMachine.Configure(State.A)
.PermitIf(Trigger.T1, State.B, () => { return cond(); }, (a,b) => { Action1(a,b); } )
.PermitIf(Trigger.T1, State.B, () => { return !cond(); }, (c) => { Action3(c); } );
stateMachine.Configure(State.B)
.PermitReentry(Trigger.T1, (a,b) => { Action1(a,b)} );
Any idea on how to do that with Stateless ?
Anyone tried to extend the library this way ?
Thanks in advance.
I have used the Quantum Leaps state machine framework quite a bit to run state machines on microcontrollers. It supports internal transitions, and it makes life a lot easier. The internal transition does not actually change state, so the state is the same after the event has been processed.
Consider the telephone call example. Let's say we need to adjust the volume. Every state would need an two extra lines: PermitReentry (AdjustVolumeEvent) and OnEntryFrom(AdjustVolumeEvent, HandleVolumeControl).
By using internal transition we only need to add a handler to a superstate (State.OffHook), which is much less verbose.
As a bonus the super states becomes much more useful as well.
Substates are great, but when state machine starts to have a number of states that have substates, the whole thing starts to be a little bit too large, and less easy to manage. As per question, is there a way to split a larger state-machine in a number of smaller sub state-machines?
Just by mean of example, think as if I have a state machine made of LoggedOutState and LoggedInState, which in turn has a number of substates, UserEditing, UserAdding, ...
I would like to define a high-level state-machine with the two states, and then a state-machine dedicated to just the LoggedIn scenarios. Then somehow make it so that triggers defined for entering in LoggedInState could start/enter a state in the lower-level state-machine, as well as triggers defined to exit LoggedInState could stop/leave a lower-level state.
Thanks all
PS we just posted also a question on StackOverflow.
The current implementation of the StateConfiguration does not expose the StateMachine that is currently configured. Not exposing the StateMachine makes it difficult and is a limitation for enriching the fluent interface using Extension Methods without changing the Stateless library itself (you have to add the current StateMachine as parameter which makes some "noise" that shouldn't be required).
This is an example of an Extension Method if you have a Trigger that flows along several states and should be automatically triggered/fired when reaching a state:
public static class StateMachineExtensions
{
public static StateMachine<TState, TTrigger>.StateConfiguration RepeatFireFor<TState, TTrigger>(
this StateMachine<TState, TTrigger>.StateConfiguration configuration,
TTrigger trigger,
IEnumerable<TState> destinations,
StateMachine<TState, TTrigger> stateMachine)
{
return configuration.OnEntry(
transition =>
{
if (!transition.IsReentry && destinations.Contains(transition.Destination))
{
stateMachine.Fire(trigger);
}
});
}
public static StateMachine<TState, TTrigger>.StateConfiguration RepeatFireFor<TState, TTrigger>(
this StateMachine<TState, TTrigger>.StateConfiguration configuration,
TTrigger trigger,
TState destination,
StateMachine<TState, TTrigger> stateMachine)
{
return RepeatFireFor(configuration, trigger, stateMachine, destination);
}
public static StateMachine<TState, TTrigger>.StateConfiguration RepeatFireFor<TState, TTrigger>(
this StateMachine<TState, TTrigger>.StateConfiguration configuration,
TTrigger trigger,
StateMachine<TState, TTrigger> stateMachine,
params TState[] destinations)
{
return RepeatFireFor(configuration, trigger, destinations, stateMachine);
}
}
This results in something like this:
stateMachine.Configure(State.SomeState)
.Permit(Trigger.GotoNext, State.FirstNextState)
.RepeatFireFor(Trigger.GotoNext, State.SecondNextState, stateMachine)
.OnEntry(DoSomethingOnEnty);
Which could be much cleaner and less error prone (client is forced, could insert the wrong state machine):
stateMachine.Configure(State.SomeState)
.Permit(Trigger.GotoNext, State.FirstNextState)
.RepeatFireFor(Trigger.GotoNext, State.SecondNextState)
.OnEntry(DoSomethingOnEnty);
... if you are able to write the Extensions this way:
public static class StateMachineExtensions
{
public static StateMachine<TState, TTrigger>.StateConfiguration RepeatFireFor<TState, TTrigger>(
this StateMachine<TState, TTrigger>.StateConfiguration configuration,
TTrigger trigger,
IEnumerable<TState> destinations)
{
return configuration.OnEntry(
transition =>
{
if (!transition.IsReentry && destinations.Contains(transition.Destination))
{
// e.g. exposed StateMachine as property here
configuration.StateMachine.Fire(trigger);
}
});
}
public static StateMachine<TState, TTrigger>.StateConfiguration RepeatFireFor<TState, TTrigger>(
this StateMachine<TState, TTrigger>.StateConfiguration configuration,
TTrigger trigger,
TState destination)
{
return RepeatFireFor(configuration, trigger, destination);
}
public static StateMachine<TState, TTrigger>.StateConfiguration RepeatFireFor<TState, TTrigger>(
this StateMachine<TState, TTrigger>.StateConfiguration configuration,
TTrigger trigger,
params TState[] destinations)
{
return RepeatFireFor(configuration, trigger, destinations);
}
}
The provision of the StateMachine by the StateConfiguration should be easy, because the StateMachine acts as Factory for the StateMachineConfiguration (even though the current StateConfiguration does not know about the TState/TTrigger generic parameters itself).
Another problem is that you do not expose the State that is Wrapped into the StateRepresentation's UnderlyingState that is currently not accessible outside of the StateConfiguration. This way you don't know what state (e.g. enum value) you are currently configuring when creating an Extension Method and you are forced to add some noise to the interface again (add the configured state as param, which the client/user already knows from the factory call .Configure(TState state).
I have a question about parameterized triggers. I need to be able to pass objects into the triggers for a state but I need to pass different objects into the same state change. Is this possible?
var createStayTrigger = sm.SetTriggerParameters(Trigger.CreateStay);
var createStayAfterItemTrigger = sm.SetTriggerParameters(Trigger.CreateStay);
sm.Configure(State.ProcessingStay)
.Permit(Trigger.Finish, State.Complete)
.Ignore(Trigger.Start)
.Ignore(Trigger.CreateStay)
.OnEntryFrom(createStayTrigger, e =>
{
// do something here with LineItemAddedEvent
})
.OnEntryFrom(createStayAfterItemTrigger, e =>
{
// do something here with ItemCreatedEvent
});
Re-posting on GitHub since I noticed project has moved:
What steps will reproduce the problem?
The ignored trigger will be listed among the Permitted triggers even though the trigger won't be allowed by yourStateMachine.CanFire(substate)
Cause seem to be the union with the superstates permittedTriggers:
public IEnumerable<TTrigger> PermittedTriggers
{
get
{
var result = _triggerBehaviours
.Where(t => t.Value.Any(a => a.IsGuardConditionMet))
.Select(t => t.Key);
if (Superstate != null)
result = result.Union(Superstate.PermittedTriggers);
return result.ToArray();
}
}
Hi.
If State and Trigger types aren't "primitive"/"scalar" types, but POCO classes, StateMachine model doesn't work at all!
Any suggestions?
Thanks.
I'm subclassing StateMachine and was hoping I would be able to find a nice way to set up OnUnhandledTrigger so that if a state transition exists for given state and transition but guard conditions are not met that the exception message could contain the text from PermitIf->guardDescription.
Sadly everything I could possibly use is either internal or private.
Would there be any interest in making more use of protected access modifier?
Ok so, this is totally a feature request and not an "issue" -- Nick just tell me if this post is in the wrong place and I'll take it down / move it :)
So, I was wondering if there is anyone who wants to try and build a visual inspector for Unity that works with Stateless together with me. This work probably doesn't belong as part of the 'Stateless' repo itself, but could be another Github project (and possibly released in the Unity Asset Store too).
Phase 1 would be a pure visualization of state hierarchy and flow during runtime.
Phase 2 would be to allow the machine to be setup through the inspector itself (would require converting a Unity editor-made diagram / meta-data into auto-generated C# code...? lol not sure)
Just a thought, would like to hear feedback on this idea from anyone who's used Stateless and Unity together ^^
This is something I do quite frequently - an OnEntry action either directly or indirectly results a call to Fire() that takes the state machine to a new state.
The problem is that because the call to Fire immediately causes a new transition, any code after the call to Fire in the OnEntry action is called after the state machine enters the new state. Here's an example:
class Program
{
enum Trigger
{
T1, T2, T3
}
enum State
{
S1, S2, S3
}
static void Main(string[] args)
{
var check = true;
var sm = new StateMachine<State, Trigger>(State.S1);
sm.Configure(State.S1)
.Permit(Trigger.T1, State.S2)
.OnEntry(() => Console.WriteLine("State S1 OnEntry action"));
sm.Configure(State.S2)
.Permit(Trigger.T2, State.S3)
.Permit(Trigger.T3, State.S1)
.OnEntry(() =>
{
Console.WriteLine("State S2 OnEntry action started");
if (check)
sm.Fire(Trigger.T2);
else
sm.Fire(Trigger.T3);
Console.WriteLine("State S2 OnEntry action complete");
});
sm.Configure(State.S3)
.Permit(Trigger.T1, State.S1)
.OnEntry(() => Console.WriteLine("State S3 OnEntry action"));
sm.Fire(Trigger.T1);
}
}
This results in the output:
State S2 OnEntry action started
State S3 OnEntry action
State S2 OnEntry action complete
I.e. S2 completes after S3.
I have a simple fix for this that add an internal queue to the state machine so that processing of triggers is carried in strict order.
Do you want the fix?
I don't if anyone here needed this, but at my project, I need to fire some actions on exit from one state.
Because of this state has the possibility to have a reentry, I can't control this only with the OnExit.
Is this a thing that only I have or does anybody had too?
Hello, sorry if this is the wrong place to post f^^;) I just pulled the latest and printed out a few of my SMs and hierarchical information doesn't seem to be represented (no sub-states) – just wanted to check if that's not currently supported or else I'm doing something wrong f^^;)
Thank you!
Arun
I want to generate list of Triggers and their Next States from current state.
Just like you exposed StateMachine.PermittedTriggers which returns list of allowed Triggers from current State, why don't you return IEnumerable NextStates.
Or there is a method that I can convert a Start State and Trigger to Next States cause I am still new :)
I know it violates FSM but it is also accepted as an extension too. (check this : http://en.wikipedia.org/wiki/State_diagram#Other_extensions and this for an example : https://today.java.net/article/2009/09/06/finite-state-machine-supporting-concurrent-states)
Is it possible to support it?
Could you please provide tagging or branching (sorry, I'm not an expert) on the source repository so that it's easier to find out what are the sources exactly matching the released NuGet packages version?
Thanks in advance.
This is not an issue per se, but i am looking for a way to turn my existing State machines into flow charts of some sort. People say that it is good for you,
To be able to achive this i reckon i would have to turn my state machine into some kind of data structure that is more easy to visualize, like a 2-dimensional array or something. I would then turn it into JSON and expose it to some SVG JavaScript library to make it all shiny.
I'm quite new to Stateless, but i wonder if anyone has done anything like this and if it is possible.
(this was originally mentioned in https://github.com/nblumhardt/stateless/issues/14#issuecomment-158979430, but I thought i'd raise a proper issue)
We are using Stateless, version 2.5.29.0 in one of our projects, which is compiled targeting .net 4.5.
During build we get a warning Found conflicts between different versions of the same dependent assembly that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed.
.
The detailed log shows:
...
5> There was a conflict between "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" and "System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes".
5> "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" was chosen because it was primary and "System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes" was not.
5> References which depend on "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" [C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Core.dll].
5> C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Core.dll
5> Project file item includes which caused reference "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Core.dll".
... (25 lines ommitted) ...
5> D:\XXX\Payments\Dev\Source\packages\NServiceBus.NHibernate.4.5.5\lib\net40\NServiceBus.NHibernate.dll
5> Project file item includes which caused reference "D:\XXX\Payments\Dev\Source\packages\NServiceBus.NHibernate.4.5.5\lib\net40\NServiceBus.NHibernate.dll".
5> NServiceBus.NHibernate, Version=4.5.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c, processorArchitecture=MSIL
... (94 lines ommitted) ...
5> References which depend on "System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes" [].
5> D:\XXX\Payments\Dev\Source\XXX\bin\Debug\Stateless.dll
5> Project file item includes which caused reference "D:\XXX\Payments\Dev\Source\XXX.Payments.Domain\bin\Debug\Stateless.dll".
5> D:\XXX\Payments\Dev\Source\XXX\bin\Debug\XXX.Payments.Domain.dll
5>C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets(1697,5): warning MSB3277: Found conflicts between different versions of the same dependent assembly that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed.
...
I've attempted to use a bindingRedirect to fix this issue, but it had no effect.
I've also attempted using the Stateless-4.0 package, but that seems to have fallen behind, and does not have the OnTransitioned functionality from nblumhardt@f63abbe, so it appears quite old.
Now, I know very little about PCL (but a lot more now than I knew an hour ago), but it seems that the root cause is the change to use PCL (nblumhardt@828d097).
I wonder if its a good idea to create a nuget package that supports .net 3.5 (which was requested in https://github.com/nblumhardt/stateless/issues/14#issuecomment-137317963), .net 4.0, .net 4.5 as well as the PCL profile 136.
What are your thoughts?
If you're of the opinion that this is a good idea, I'll take a look at the implementation, most likely using build configurations, and see if I can put together a PR.
I would have expected this behaviour, because it is something like a reentrance into the state.
[TestFixture]
public class StateRepresentationFixture
{ // extends StateRepresentationFixture
[Test]
public void WhenEnteringSuperstateFromSubstate_SuperstateEntryActionsExecuted()
{
StateMachine<State, Trigger>.StateRepresentation super;
StateMachine<State, Trigger>.StateRepresentation sub;
CreateSuperSubstatePair(out super, out sub);
bool executed = false;
super.AddEntryAction((t,a) => executed = true );
var transition = new StateMachine<State, Trigger>.Transition(sub.UnderlyingState, super.UnderlyingState, Trigger.X);
super.Enter(transition);
Assert.IsTrue(executed);
}
[Test]
public void WhenExitingSubstateToSuperstate_SuperstateExitActionsExecuted()
{
StateMachine<State, Trigger>.StateRepresentation super;
StateMachine<State, Trigger>.StateRepresentation sub;
CreateSuperSubstatePair(out super, out sub);
bool executed = false;
super.AddExitAction(t => executed = true );
var transition = new StateMachine<State, Trigger>.Transition(sub.UnderlyingState, super.UnderlyingState, Trigger.X);
sub.Exit(transition);
Assert.IsTrue(executed);
}
}
Here are the changes for this
public void Enter(Transition transition, params object[] entryArgs)
{
Enforce.ArgumentNotNull(transition, "transtion");
if (transition.IsReentry || Includes(transition.Source)) // here
{
ExecuteEntryActions(transition, entryArgs);
}
else if (!Includes(transition.Source))
{
if (_superstate != null)
_superstate.Enter(transition, entryArgs);
ExecuteEntryActions(transition, entryArgs);
}
}
public void Exit(Transition transition)
{
Enforce.ArgumentNotNull(transition, "transtion");
if (transition.IsReentry || Includes(transition.Destination)) // here
{
ExecuteExitActions(transition);
}
else if (!Includes(transition.Destination))
{
ExecuteExitActions(transition);
if (_superstate != null)
_superstate.Exit(transition);
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.