C#是否包含有限状态机?

时间:2009-09-10 18:40:44

标签: c# .net design-patterns finite-automata fsm

我最近读过关于boost::statechart库(有限状态机)的文章,我很喜欢这个概念。

C#是否有类似的机制?或者可以使用特定的设计模式实现吗?

8 个答案:

答案 0 :(得分:18)

.NET 4 Update 1现在支持以下类: System.Activities.Statements.StateMachine

这是tutorial on how to use it。 这是一个hands on lab

答案 1 :(得分:8)

Workflow Foundation (.NET 3.0)有一个状态机工作流程。 4.0目前没有完全相同的东西,但你绝对可以使用4.0创建一个状态机工作流程。

答案 2 :(得分:6)

我维护了一个开源项目,该项目实现了.NET的通用有限状态机(除此之外)。它建立在QuickGraph之上,因此您可以免费获得许多图形分析算法。

有关该项目的详情,请参阅this page,有关该功能的更多信息,请参见“Jolt.Automata : Finite State Machines”。

答案 3 :(得分:6)

查看无状态 - > http://code.google.com/p/stateless/。它是重型WWF的轻量级替代品。

以下是该工具的作者的几篇文章:

State Machines in Domain Models

Parameterised Triggers and Re-entrant States in Stateless

答案 4 :(得分:2)

接近FSM的是.NET 3.5中的工作流程,但是,工作流程也不完全是FSM。

使用FSM的强大之处在于,您可以在代码中创建显式,从而减少创建错误的机会。此外,当然有些系统本质上是FSM,所以对它们进行编码就更自然了。

答案 5 :(得分:1)

Windows Workflow Foundation(WF)是3.0和3.5中基类库的一部分,它包括一个状态机工作流设计,用于管理应用程序的状态机。

他们已完全重写了即将发布的4.0版本的工作流程,而新的WF 4.0类本身并不支持状态机,但4.0版本仍然完全支持所有3.0 / 3.5类。

答案 6 :(得分:0)

是的,C#有iterator blocks,它们是编译器生成的状态机。

如果您希望实现自己的状态机,可以创建IEnumerable<T>IEnumerator<T>接口的自定义实现。

这两种方法都突出了.NET框架对iterator pattern的实现。

答案 7 :(得分:-1)

此存储库https://github.com/lingkodsoft/StateBliss中的其他替代方法 使用流利的语法,支持触发器。

    public class BasicTests
    {
        [Fact]
        public void Tests()
        {
            // Arrange
            StateMachineManager.Register(new [] { typeof(BasicTests).Assembly }); //Register at bootstrap of your application, i.e. Startup
            var currentState = AuthenticationState.Unauthenticated;
            var nextState = AuthenticationState.Authenticated;
            var data = new Dictionary<string, object>();

            // Act
            var changeInfo = StateMachineManager.Trigger(currentState, nextState, data);

            // Assert
            Assert.True(changeInfo.StateChangedSucceeded);
            Assert.Equal("ChangingHandler1", changeInfo.Data["key1"]);
            Assert.Equal("ChangingHandler2", changeInfo.Data["key2"]);
        }

        //this class gets regitered automatically by calling StateMachineManager.Register
        public class AuthenticationStateDefinition : StateDefinition<AuthenticationState>
        {
            public override void Define(IStateFromBuilder<AuthenticationState> builder)
            {
                builder.From(AuthenticationState.Unauthenticated).To(AuthenticationState.Authenticated)
                    .Changing(this, a => a.ChangingHandler1)
                    .Changed(this, a => a.ChangedHandler1);

                builder.OnEntering(AuthenticationState.Authenticated, this, a => a.OnEnteringHandler1);
                builder.OnEntered(AuthenticationState.Authenticated, this, a => a.OnEnteredHandler1);

                builder.OnExiting(AuthenticationState.Unauthenticated, this, a => a.OnExitingHandler1);
                builder.OnExited(AuthenticationState.Authenticated, this, a => a.OnExitedHandler1);

                builder.OnEditing(AuthenticationState.Authenticated, this, a => a.OnEditingHandler1);
                builder.OnEdited(AuthenticationState.Authenticated, this, a => a.OnEditedHandler1);

                builder.ThrowExceptionWhenDiscontinued = true;
            }

            private void ChangingHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
            {
                var data = changeinfo.DataAs<Dictionary<string, object>>();
                data["key1"] = "ChangingHandler1";
            }

            private void OnEnteringHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
            {
                // changeinfo.Continue = false; //this will prevent changing the state
            }

            private void OnEditedHandler1(StateChangeInfo<AuthenticationState> changeinfo)
            {                
            }

            private void OnExitedHandler1(StateChangeInfo<AuthenticationState> changeinfo)
            {                
            }

            private void OnEnteredHandler1(StateChangeInfo<AuthenticationState> changeinfo)
            {                
            }

            private void OnEditingHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
            {
            }

            private void OnExitingHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
            {
            }

            private void ChangedHandler1(StateChangeInfo<AuthenticationState> changeinfo)
            {
            }
        }

        public class AnotherAuthenticationStateDefinition : StateDefinition<AuthenticationState>
        {
            public override void Define(IStateFromBuilder<AuthenticationState> builder)
            {
                builder.From(AuthenticationState.Unauthenticated).To(AuthenticationState.Authenticated)
                    .Changing(this, a => a.ChangingHandler2);

            }

            private void ChangingHandler2(StateChangeGuardInfo<AuthenticationState> changeinfo)
            {
                var data = changeinfo.DataAs<Dictionary<string, object>>();
                data["key2"] = "ChangingHandler2";
            }
        }
    }

    public enum AuthenticationState
    {
        Unauthenticated,
        Authenticated
    }
}