我使用Stateless在多个类中实现FSM。 (http://code.google.com/p/stateless/)
我想使用基类来触发触发器和日志记录等。 我还想强制继承我的baseFSM类的任何类使用它们自己的本地状态和触发器实现StateMachine。
然而我的问题是,枚举不能被抽象或传递给函数。
顺便说一下,Stateless说“对任何.NET类型(数字,字符串,枚举等)的状态和触发器的通用支持”,所以如果有更好的方法可以解决这个问题,请告诉我。
理想情况下,这是我想要实现的(或者可以以相同方式工作的东西)。
BaseFSM类:
public abstract class BaseFSM : IStateMachine
{
#region Implementation of IStateMachine
public ICall LocalCall { get; set; }
#endregion
internal abstract enum State {}
internal abstract enum Trigger {}
internal abstract StateMachine<State, Trigger> fsm { get; set; }
public abstract void Fire(Enum trigger);
}
实现BaseFSM的类:
class Incoming_Initial : BaseFSM
{
private enum State
{
WaitForCallToBeAnswered,
CallConnected,
CallNeverConnected,
CheckForCustomIntro,
PlayIntro,
PlayPleaseEnterPin,
ReadLanguageSettings,
ChooseLanguage,
ValidatePIN,
PINWasInvalid,
IdentifyUser
}
private enum Trigger
{
Yes,
No,
DigitPressed,
PromptDonePlaying,
PromptTimerElapse,
Done
}
public Incoming_Initial(ICall call)
{
LocalCall = call;
fsm = new StateMachine<this.State, this.Trigger>(State.WaitForCallToBeAnswered);
....
或者我甚至会采取这样的方式:
public class myStateMachine
{
private enum State{}
private enum Trigger{}
private StateMachine<State, Trigger> stateMachine;
public myStateMachine (Enum _states, Enum _triggers, Enum _startState)
{
State = _states;
Trigger = _triggers;
stateMachine = new StateMachine<State, Trigger>(_startState);
}
}
非常感谢任何关于如何实现这一点的见解!
编辑:我的最终目标是使用Stateless来实现具有~40个不同FSM的IVR(IVR)系统。状态机将负责呼叫流程以及用户与系统的交互方式。我已经有一个演示状态机工作,但状态和触发器是该类的本地。
我只是想看看我是否可以将状态机拉出到基类,所以我不必将状态机传递给辅助函数。
如果我可以将状态机放在基类中,我想我可以使用一组触发器(这些是来自电话呼叫的事件,如CallConnected,UserPressedDigit,CallDisconnected,PromptDonePlaying等),只需要实现状态对于每个FSM。
ANSWER(至少我如何使用它)感谢@phoog:
public abstract class BaseFSM <TState> : IStateMachine
{
#region Implementation of IStateMachine
public ICall LocalCall { get; set; }
#endregion
public enum Triggers
{
Yes = 0,
No,
DigitPressed,
PromptDonePlaying,
PromptTimerElapse,
Done
}
protected IList<TState> States { get; set; }
protected StateMachine<TState, Triggers> fsm { get; set; }
...
class Incoming_Initial : BaseFSM<Incoming_Initial.State>
{
internal enum State
{
WaitForCallToBeAnswered,
CallConnected,
CallNeverConnected,
CheckForCustomIntro,
PlayIntro,
PlayPleaseEnterPin,
ReadLanguageSettings,
ChooseLanguage,
ValidatePIN,
PINWasInvalid,
IdentifyUser
}
public Incoming_Initial(ICall call)
{
LocalCall = call;
LocalCall.CallEventHandler += new CallEventHandler(LocalCall_CallEventHandler);
States = (State[]) Enum.GetValues(typeof (State));
fsm = new StateMachine<State, Triggers>(State.WaitForCallToBeAnswered);
答案 0 :(得分:2)
请注意,Enum
类型表示对枚举的盒装值的引用;它没有引用整个枚举类型。因此,例如,此代码有效:
enum Something { Value0, Value1, Value2, Value3 }
void ProcessAnEnumValue(Enum value)
{
//...whatever
}
void CallTheMethod()
{
ProcessAnEnumValue(Something.Value2);
}
您正在尝试参数化整个枚举类型;参数化类型的工具是泛型。考虑到这一点,您的代码可以使用一些修改:
public abstract class BaseFSM<TState, TTrigger> : IStateMachine
{
#region Implementation of IStateMachine
public ICall LocalCall { get; set; }
#endregion
protected IList<TState> States { get; set; }
protected IList<TTrigger> Triggers { get; set; }
protected StateMachine<TState, TTrigger> fsm { get; set; }
public abstract void Fire(TTrigger trigger);
}
class Incoming_Initial : BaseFSM<Incoming_Initial.State, Incoming_Initial.Trigger>
{
public enum State
{
WaitForCallToBeAnswered,
CallConnected,
CallNeverConnected,
CheckForCustomIntro,
PlayIntro,
PlayPleaseEnterPin,
ReadLanguageSettings,
ChooseLanguage,
ValidatePIN,
PINWasInvalid,
IdentifyUser
}
public enum Trigger
{
Yes,
No,
DigitPressed,
PromptDonePlaying,
PromptTimerElapse,
Done
}
public Incoming_Initial(ICall call)
{
States = (State[])Enum.GetValues(typeof(State));
Triggers = (Trigger[])Enum.GetValues(typeof(Trigger));
LocalCall = call;
fsm = new StateMachine<State, Trigger>(State.WaitForCallToBeAnswered);
....
答案 1 :(得分:1)
你不能用枚举来做到这一点,
没有针对不同枚举的“基类”(内部存在,对于ValueType-s等,但你不能使用它 - 枚举。有方法来处理枚举GetValues等但是这是目前为止就这样)。
如果我是你,我会让你的'枚举'真的成为单独的类,所以每个状态和事件/触发器都有自己的表示类 - 并给它们所有可以共享的基类(我的意思是一个状态)一个用于触发器。) 然后你也可以使用一些状态机模式来浏览状态,并在它们之间切换。
或者取决于你可能拥有的东西,你可能想要雇用一个访问者(如果你有一个更复杂的层次结构等)来处理事情等(但这是针对更复杂的情况并结合不同的模式,这通常是必要的)。
很难说,缺少一些细节,你想用它做什么,目标等大图,有很多方法。