繁体   English   中英

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

[英]Local instance of a base enum or passing enum collection?

我使用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实现状态。

答案(至少我如何使用这个)感谢@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的盒装值的引用; 它没有引用整个枚举类型。 因此,例如,此代码有效:

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

你不能用枚举,
对于不同的枚举没有“基类” (内部有,对于ValueType-s等,但是你不能使用它 - 枚举。有方法来处理枚举GetValues等但是那就是这样)。

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

或者根据您可能拥有的内容,您可能希望使用访问者(如果您有更复杂的层次结构等)来处理事物等(但这是针对更复杂的情况并组合不同的模式,这通常是必要的)。
很难说,缺少一些细节,你想用它做什么,目标等大图,有很多方法。

免责声明:不熟悉您所指的“无国籍”,也可能采用其他方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM