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

时间:2012-04-03 18:08:49

标签: c# enums function-parameter

我使用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);

2 个答案:

答案 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等但是这是目前为止就这样)。

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

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

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