基本枚举的本地实例或传递枚举集合?
我正在使用无状态来实现多个类中的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);
....
你不能做到这一点与枚举,
有不同的枚举没有“基地班”(有内部的,对于ValueType-s等,但你不能使用它 - Enum。有处理枚举GetValues等的方法,但是就这一点而言)。
如果我是你,我会让你的'枚举'成为单独的类,所以每个状态和事件/触发器都有它们自己的表示类 - 并给它们所有可以共享的基类(我的意思是说一个触发器)。
然后你也可以使用一些状态机模式来遍历状态,并在它们之间翻转。
或者取决于你可能想要雇用的访问者(如果你有更复杂的层次结构等)通过事情等。(但那是更复杂的情况,并结合不同的模式,这往往是必要的)。
很难说,缺少一些更多的细节,你想做什么,目标等大图,有很多方法。
免责声明:不熟悉你指的“无状态”,所以可能有其他方式。
我更新了我的帖子,我的最终目标。 – jpiccolo 2012-04-03 19:42:17
现在,如果非常棒!非常感谢你! – jpiccolo 2012-04-03 20:14:49
这是他需要的一个很好的答案!但Enum并没有给泛型提供任何强大的输入和约束 - 你也可以使用对象并且不会有太大的区别。顺便说一句。你应该将泛型限制在:struct至少(这是可能的)。 – NSGaga 2012-04-03 23:05:59
@NSGaga当然你是对的。我没有添加任何约束,因为他们似乎不必要;如果你使用了*不是*枚举的类型,那么基类中就没有任何东西会被破坏。 Jon Skeet有一个名为“无限制旋律”的项目,允许你通过重写IL来应用枚举约束--CLR支持枚举约束,只有C#不支持。 – phoog 2012-04-04 14:39:02