基本枚举的本地实例或传递枚举集合?

问题描述:

我正在使用无状态来实现多个类中的FSM。 (http://code.google.com/p/stateless/基本枚举的本地实例或传递枚举集合?

我想用一个基类激活触发器和记录等。 我也想强制执行,任何类继承我的baseFSM类实现自己的本地国和触发状态机。

但是我的问题是,枚举的不能被抽象或传递给函数。顺便说一下,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); 
     .... 

OR我甚至会采取这样的事情:

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

我如何能去任何有识之士关于实施这个将不胜感激!

编辑:我的最终目标是使用无状态来实现具有40个不同FSM的IVR(IVR)系统。状态机将负责呼叫流程以及用户与系统的交互方式。我已经有一个演示状态机工作,但状态和触发器是本地的。

我只是想看看我是否可以将状态机拉出到基类,所以我不必将状态机传递给辅助函数。如果我可以把状态机放在一个基类中,我想我可以使用一组触发器(这些是来自CallConnected,UserPressedDigit,CallDisconnected,PromptDonePlaying等电话的事件),并且只需要实现每个FSM的状态。

的答案(至少我是如何使用这个)由于@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); 

请注意,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); 
     .... 
+0

现在,如果非常棒!非常感谢你! – jpiccolo 2012-04-03 20:14:49

+0

这是他需要的一个很好的答案!但Enum并没有给泛型提供任何强大的输入和约束 - 你也可以使用对象并且不会有太大的区别。顺便说一句。你应该将泛型限制在:struct至少(这是可能的)。 – NSGaga 2012-04-03 23:05:59

+0

@NSGaga当然你是对的。我没有添加任何约束,因为他们似乎不必要;如果你使用了*不是*枚举的类型,那么基类中就没有任何东西会被破坏。 Jon Skeet有一个名为“无限制旋律”的项目,允许你通过重写IL来应用枚举约束--CLR支持枚举约束,只有C#不支持。 – phoog 2012-04-04 14:39:02

你不能做到这一点与枚举,
有不同的枚举没有“基地班”(有内部的,对于ValueType-s等,但你不能使用它 - Enum。有处理枚举GetValues等的方法,但是就这一点而言)。

如果我是你,我会让你的'枚举'成为单独的类,所以每个状态和事件/触发器都有它们自己的表示类 - 并给它们所有可以共享的基类(我的意思是说一个触发器)。
然后你也可以使用一些状态机模式来遍历状态,并在它们之间翻转。

或者取决于你可能想要雇用的访问者(如果你有更复杂的层次结构等)通过事情等。(但那是更复杂的情况,并结合不同的模式,这往往是必要的)。
很难说,缺少一些更多的细节,你想做什么,目标等大图,有很多方法。

免责声明:不熟悉你指的“无状态”,所以可能有其他方式。

+0

我更新了我的帖子,我的最终目标。 – jpiccolo 2012-04-03 19:42:17