Ich verwende Stateless, um FSMs in mehreren Klassen zu implementieren. (http://code.google.com/p/stateless/)Lokale Instanz einer Base Enum oder Passing Enum Collection?
Ich mag eine Basisklasse zum Brennen von Triggern und Protokollierung verwenden, etc .. Ich mag auch erzwingen, dass jede Klasse erbt meine baseFSM Klasse eine Statemachine mit ihren eigenen lokalen Staaten und Trigger implementiert.
Allerdings ist mein Problem, enum kann nicht abstrahiert oder an Funktionen übergeben werden.
Übrigens sagt Staatenlos "Generische Unterstützung für Zustände und Auslöser von jedem .NET-Typ (Zahlen, Strings, enums, etc.)" also, wenn es einen besseren Weg gibt, darüber zu gehen, lass es mich wissen.
Idealerweise möchte ich das implementieren (oder etwas, das auf die gleiche Weise funktionieren kann).
BaseFSM Klasse:
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);
}
Eine Klasse, die BaseFSM implementiert:
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 ich so etwas wie dies würde auch nehmen:
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);
}
}
ich gehen kann Einsicht darüber, wie über die Umsetzung dieses würde sehr geschätzt werden!
Bearbeiten: Mein ultimatives Ziel ist die Verwendung von Staatenlos, ein IVR (IVR) System zu implementieren, das ~ 40 verschiedene FSM hat. Die Zustandsautomaten sind verantwortlich für den Anrufverlauf und wie der Benutzer mit dem System interagiert. Ich habe bereits eine Demo-Zustandsmaschine, aber die States und Trigger sind lokal in dieser Klasse.
Ich versuche nur zu sehen, ob ich die Zustandsmaschine zu einer Basisklasse herausziehen kann, so dass ich die Zustandsmaschine nicht an Hilfsfunktionen übergeben muss.
Wenn ich die State Machine in eine Basisklasse legen kann, denke ich, ich könnte einen Satz von Triggern verwenden (dies wären Ereignisse aus dem Telefonanruf wie CallConnected, UserPressedDigit, CallDisconnected, PromptDonePlaying, etc) und müssen nur implementieren Staaten für jede FSM.
ANTWORT (zumindest, wie ich das bin mit) dank @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);
Jetzt das, wenn sehr fantastisch! Vielen Dank! – jpiccolo
das ist eine gute antwort für was er braucht! Aber Enum gibt Generika keine starke Typisierung oder Beschränkung - Sie könnten genauso gut Objekte verwenden und würden sich nicht sehr unterscheiden. Übrigens. Sie sollten die generics beschränken auf: struct mindestens (das ist, was möglich ist). – NSGaga
@NSGaga Sie sind natürlich richtig. Ich fügte keine Einschränkungen hinzu, weil sie nicht notwendig erschienen. Es gibt nichts in der Basisklasse, das brechen würde, wenn Sie einen Typ verwenden, der * nicht enum ist. Jon Skeet hat ein Projekt namens "unbeschränkte Melodie", mit dem Sie Enum-Constraints anwenden können, indem Sie IL umschreiben - die CLR unterstützt Enum-Constraints, nur C# nicht. – phoog