Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 转换到目标状态并触发之间的转换和状态的状态机?_.net_State Machine_Stateless State Machine - Fatal编程技术网

.net 转换到目标状态并触发之间的转换和状态的状态机?

.net 转换到目标状态并触发之间的转换和状态的状态机?,.net,state-machine,stateless-state-machine,.net,State Machine,Stateless State Machine,我最近使用了状态机。我可以定义转换等的规则,如下所示: stateMachine.Configure(State.Unknown) .Permit(Trigger.StartApplication, State.Initialized) .OnEntry(this.DoBeforeTransition) .OnExit(this.DoAfterTransition); stateMachine.Configure(State.Initialized) .Perm

我最近使用了状态机。我可以定义转换等的规则,如下所示:

stateMachine.Configure(State.Unknown)
    .Permit(Trigger.StartApplication, State.Initialized)
    .OnEntry(this.DoBeforeTransition)
    .OnExit(this.DoAfterTransition);

stateMachine.Configure(State.Initialized)
    .Permit(Trigger.CheckSomething, State.SomethingChecked)
    .OnEntry(this.DoBeforeTransition)
    .OnExit(this.DoAfterTransition);

然后你可以触发一个触发器来改变状态。但是,如果要转到特定状态,则需要知道当前状态以及下一个状态。因此,如果没有定义直接转换,状态机的“客户机”需要了解如何达到特定状态。是否有可能调用“goto”之类的命令,而机器会触发所有需要的触发器?

如果每个状态只有一个“Permit”,您可以这样做。如果您有多个“许可证”,则无法在工作流中自动移动(您选择一个许可证/触发器而不是另一个许可证/触发器必须有某种原因)。当我说你“不能”时,这不是技术上的,而是实际上的

下面是在工作流中自动移动的示例

using Stateless;
using System;
using System.Runtime.CompilerServices;

namespace MyExample.BAL.WorkFlows
{
    public class TelephoneCallWorkFlow
    {

        private static volatile StateMachine<TelephoneCallStateEnum, TelephoneCallTriggerEnum> SingletonInstance;

        public StateMachine<TelephoneCallStateEnum, TelephoneCallTriggerEnum> Instance
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            get
            {
                if (SingletonInstance == null)
                {
                    SingletonInstance = new StateMachine<TelephoneCallStateEnum, TelephoneCallTriggerEnum>(TelephoneCallStateEnum.OffHook);

                    SingletonInstance.Configure(TelephoneCallStateEnum.OffHook)
                        .Permit(TelephoneCallTriggerEnum.CallDialed, TelephoneCallStateEnum.Ringing);

                    SingletonInstance.Configure(TelephoneCallStateEnum.Ringing)
                        //removing so there is only one valid path workflow//.Permit(TelephoneCallTriggerEnum.HungUp, TelephoneCallStateEnum.OffHook)
                        .Permit(TelephoneCallTriggerEnum.CallConnected, TelephoneCallStateEnum.Connected);

                    SingletonInstance.Configure(TelephoneCallStateEnum.Connected)
                        //.OnEntry(t => StartCallTimer())
                        //.OnExit(t => StopCallTimer())
                        //removing so there is only one valid path workflow//.Permit(TelephoneCallTriggerEnum.LeftMessage, TelephoneCallStateEnum.OffHook)
                        //removing so there is only one valid path workflow//.Permit(TelephoneCallTriggerEnum.HungUp, TelephoneCallStateEnum.OffHook)
                        .Permit(TelephoneCallTriggerEnum.PlacedOnHold, TelephoneCallStateEnum.OnHold)
                        ;

                    SingletonInstance.Configure(TelephoneCallStateEnum.OnHold)
                        //removing so there is only one valid path workflow//.SubstateOf(TelephoneCallStateEnum.Connected)
                        //removing so there is only one valid path workflow//.Permit(TelephoneCallTriggerEnum.TakenOffHold, TelephoneCallStateEnum.Connected)
                        //removing so there is only one valid path workflow//.Permit(TelephoneCallTriggerEnum.HungUp, TelephoneCallStateEnum.OffHook)
                        .Permit(TelephoneCallTriggerEnum.PhoneHurledAgainstWall, TelephoneCallStateEnum.PhoneDestroyed)
                        ;
                }

                return SingletonInstance;
            }
        }

        public void Fire(TelephoneCallTriggerEnum trigger)
        {
            Console.WriteLine("............[Firing:] {0}", trigger);
            this.Instance.Fire(trigger);
        }
    }
}

public enum TelephoneCallStateEnum
{
    OffHook,
    Ringing,
    Connected,
    OnHold,
    PhoneDestroyed
}

public enum TelephoneCallTriggerEnum
{
    CallDialed,
    HungUp,
    CallConnected,
    LeftMessage,
    PlacedOnHold,
    TakenOffHold,
    PhoneHurledAgainstWall
}
使用无状态;
使用制度;
使用System.Runtime.CompilerServices;
命名空间MyExample.BAL.WorkFlows
{
公共类工作流程
{
私有静态易失性状态机;
公共状态机实例
{
[MethodImpl(MethodImplOptions.Synchronized)]
得到
{
if(singletonistance==null)
{
SingletonInstance=新状态机(TelephoneCallStateEnum.OffHook);
配置(电话CallStateEnum.OffHook)
.Permit(TelephoneCallTriggerEnum.CallDialed、telephonecallstatenum.Ringing);
SingletonInstance.Configure(电话呼叫状态枚举.Ringing)
//正在删除,以便只有一个有效路径工作流//.Permit(TelephoneCallTriggerEnum.HungUp、TelephoneCallStateEnum.OffHook)
.Permit(TelephoneCallTriggerEnum.CallConnected,telephonecallstatenum.Connected);
配置(电话CallStateEnum.Connected)
//.OnEntry(t=>StartCallTimer())
//.OnExit(t=>StopCallTimer())
//正在删除,以便只有一个有效路径工作流//.Permit(TelephoneCallTriggerEnum.LeftMessage、TelephoneCallStateEnum.OffHook)
//正在删除,以便只有一个有效路径工作流//.Permit(TelephoneCallTriggerEnum.HungUp、TelephoneCallStateEnum.OffHook)
.Permit(TelephoneCallTriggerEnum.PlacedOnHold、TelephoneCallStateEnum.OnHold)
;
配置(电话CallStateEnum.OnHold)
//正在删除,因此只有一个有效路径workflow/.SubstateOf(TelephoneCallStateEnum.Connected)
//正在删除,以便只有一个有效路径工作流//.Permit(TelephoneCallTriggerEnum.TakenOffHold,TelephoneCallStateEnum.Connected)
//正在删除,以便只有一个有效路径工作流//.Permit(TelephoneCallTriggerEnum.HungUp、TelephoneCallStateEnum.OffHook)
.Permit(TelephoneCallTriggerEnum.PhoneHurledAgainstWall、TelephoneCallStateEnum.PhoneDistromed)
;
}
回归单一立场;
}
}
公共无效火灾(TelephoneCallTriggerEnum触发器)
{
Console.WriteLine(“………[Firing:{0}”,触发器);
此.Instance.Fire(触发器);
}
}
}
公共枚举电话CallStateEnum
{
摘机,
响铃,
有联系的,
暂停,
电话被毁
}
公用枚举电话调用TriggerEnm
{
拨打,
HungUp,
呼叫连接,
LeftMessage,
PlacedOnHold,
外挂,
电话呼啸而过
}
现在是“自动移动”技巧

TelephoneCallWorkFlow tcwf1=新建TelephoneCallWorkFlow();
IEnumerable myPermittedTriggers=tcwf1.Instance.PermittedTriggers;
while(null!=myPermittedTriggers&&myPermittedTriggers.Count()>0)
{
如果(myPermittedTriggers.Count()>1)
{
抛出新ArgumentOutOfRangeException(“当存在多个触发器时,无法自动移动工作流”);
}
TelephoneCallTriggerEnum nextTrigger=myPermittedTriggers.FirstOrDefault();
WriteLine(“即将调用'next'触发器:-->{0}”,nextTrigger);
tcwf1.火灾(下一个触发器);
WriteLine(“CurrentState:-->{0}”,tcwf1.Instance.State);
myPermittedTriggers=tcwf1.Instance.PermittedTriggers;
}
基本上,您可以获得PermittedTriggers,并获得第一个触发器(对于自动移动,每个状态应该只有一个允许的触发器)…然后调用该触发器

同样,实际上(不是技术上)只有在每个州有一个许可证/触发器的情况下,您才会这样做。因此,如果超过1,为什么我会有一个例外。如果超过1个,你可以“获得第一个”,这根本没有任何意义

            TelephoneCallWorkFlow tcwf1 = new TelephoneCallWorkFlow();
            IEnumerable<TelephoneCallTriggerEnum> myPermittedTriggers = tcwf1.Instance.PermittedTriggers;
            while (null != myPermittedTriggers && myPermittedTriggers.Count() > 0)
            {
                if (myPermittedTriggers.Count() > 1)
                {
                    throw new ArgumentOutOfRangeException("You cannot auto-move the workflow when there's more than one trigger");
                }
                TelephoneCallTriggerEnum nextTrigger = myPermittedTriggers.FirstOrDefault();
                Console.WriteLine("About to call the 'next' trigger: --> {0}", nextTrigger);
                tcwf1.Fire(nextTrigger);
                Console.WriteLine("CurrentState: --> {0}", tcwf1.Instance.State);
                myPermittedTriggers = tcwf1.Instance.PermittedTriggers;
            }