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