Git Product home page Git Product logo

stateless's People

Contributors

abalfour avatar angularsen avatar arturkarbone avatar celloza avatar cmendible avatar crozone avatar deepakparamkusam avatar drdavient avatar edgars-pivovarenoks avatar ffmathy avatar fjod avatar henius84 avatar henningnt avatar henningtorsteinsenbouvet avatar lakritzator avatar leeoades avatar mclift avatar nblumhardt avatar p-m-j avatar pardahlman avatar pdinnissen avatar pentp avatar pete-craig avatar polargoose avatar smnbackwards avatar surajgupta avatar tlk avatar trgrote avatar vip32 avatar yevhen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stateless's Issues

Error handling during transition

How can errors be handled during state transition? Say, an error caused during OnEntry, or OnExit which shouldn't be causing the state change.

Yet another cannot install and use in VS 201x issue

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

VS 2012

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).

Use a default constructor

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)

how can i know the source state?

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....

best practice for parameterized triggers in conjunction with a domain object?

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?

Querying StateMachine for current State

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!

Force State

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.

"Live" state-machine information with ToDotGraph()

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 ?

Question, how to ignore triggers with certain parameter values?

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

Example / Documentation Around Persistence

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

OnEntryFrom() and InternalTransition() overloads consistency

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?

Concurrent States

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

how can i fire with some args?

stateMachine.Configure("a").onEntry( id => OnEntryWithID(id) )

private void OnEntryWithID(int id)
{
Console.Write("id={0}",id);
}

stateMachine.Fire("a", 1111);

very thanks!!!!!!!!!!!!!!!!!!

PermitIfElse

Given PermitIf takes a Boolean guard clause, it would be useful to have a PermitIfElse function:

PermitIfElse(trigger, stateIfTrue, stateIfFalse, Func guard)

C#6.0

Would an upgrade to new standards be a good idea at this point or wait for v2.

MissingManifestResourceException in build 2.5.79

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".

Target .NET Core

Now that .NET Core is out Stateless makes sense as a project that targets .NET core

Please update Nuget version

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.

Please update Stateless to support .NET 4

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.StateMachine2.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.

Trigger history for compound transitions

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?

Be able to provide external configuration

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.

OnExit() called for all transitions upon Fire() call

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.

Runtime visualization through a customizable ToString method

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

Support Async OnEntry, OnExit actions

Async tasks are currently fired, and forgotten. Things can get mangled up easily. An AsyncState machine requires three behaviors:

  1. Queued actions
  2. Fire and Forget
  3. Fire only after completion, or drop.

Thoughts?

Transition / Actions

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 :
dessin1

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.

Can we have InternalTransition, please?

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.

How to split a larger statemachine in separate sub-statemachines as distinct classes?

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.

StateConfiguration does not expose configured State and the StateMachine itself

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).

Parameterized triggers and multiple entry methods

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
});

Ignored triggers are included in permittedTriggers

Re-posting on GitHub since I noticed project has moved:

What steps will reproduce the problem?

  1. Create a Statemachine with substates
  2. In a substate Ignore a trigger allowed in it's Superstate
  3. Transition your state machine to above substate
  4. Examine yourStateMachine.ToString()

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();
            }
        }

Allow IEquatable states and triggers

Hi.

If State and Trigger types aren't "primitive"/"scalar" types, but POCO classes, StateMachine model doesn't work at all!

Any suggestions?

Thanks.

Access Modifiers are very restrictive

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?

Unity Visual Inspector

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 ^^

Firing triggers from OnEntry/OnExit actions.

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?

ExitFrom

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?

Hierarchical state representation in dotgraph?

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

List Triggers and their Next States from current State

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 :)

Tagging in source tree to match NuGet package releases.

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.

Visualizable data representation of the State machine

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.

Build warning MSB3277 due to reference to System.Core, Version=2.0.5.0

(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.

Transition from SubState to SuperState

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);
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.