web-dev-qa-db-ja.com

C#には有限状態マシンが含まれていますか?

boost::statechartライブラリ(有限状態マシン)について最近読んだことがあり、そのコンセプトが気に入りました。

C#にも同様のメカニズムがありますか?または、特定の設計パターンを使用して実装できますか?

27
Maciek

はい、C#には イテレーターブロック があり、これはコンパイラー生成のステートマシンです。

独自のステートマシンを実装する場合は、IEnumerable<T>およびIEnumerator<T>インターフェースのカスタム実装を作成できます。

これらのアプローチはどちらも、.NETフレームワークによる イテレータパターン の実装を強調しています。

1
Andrew Hare

.NET 4 Update 1は、次のクラスでそれをサポートするようになりました: System.Activities.Statements.StateMachine

これが 使い方のチュートリアル です。これが 実習 です。

18
Alex

Workflow Foundation(.NET 3.0) にはステートマシンワークフローがあります。現在、4.0にはまったく同じ機能はありませんが、4.0を使用してステートマシンワークフローを確実に作成できます。

8
Will

(とりわけ).NETの一般的な有限状態マシンを実装するオープンソースプロジェクトを維持しています。 QuickGraph の上に構築されているため、多くのグラフ分析アルゴリズムを無料で入手できます。

プロジェクトの詳細については このページ を、機能の詳細については特に " Jolt.Automata:Finite State Machines "を参照してください。

6
Steve Guidi

ステートレス-> http://code.google.com/p/stateless/ を確認してください。より重いWWFの軽量な代替品です。

ツールの作成者によるいくつかの記事を次に示します。

ドメインモデルのステートマシン

パラメーター化されたトリガーとステートレスのリエントラント状態

6
J.D.

FSMに近づくのは.NET 3.5のワークフローですが、ワークフローも厳密にはFSMではありません。

FSMを使用する利点は、コード内でFSMを作成できることです明示的に、バグを作成する可能性が低くなります。その上、もちろん一部のシステムは本質的にFSMなので、そのようにコーディングする方が自然です。

3
Henri

3.0および3.5の基本クラスライブラリの一部であるWindows Workflow Foundation(WF)には、アプリケーションのステートマシンを管理するためのステートマシンワークフローデザインが含まれています。

次の4.0リリースのワークフローは完全に書き直され、新しいWF 4.0クラスはステートマシンをネイティブでサポートしていませんが、3.0/3.5クラスはすべて4.0でも完全にサポートされています。

1
Bytemaster

このリポジトリの他の代替 ​​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
    }
}

0
mcdm