/// <summary> /// <see cref="Transition"/>クラスの新しいインスタンスを初期化する. /// </summary> /// <param name="nextState">遷移先の状態. /// nullを指定すると, この遷移は内部遷移となる.(NotImplemented)</param> /// <param name="transitionMethod">遷移時に実行する処理. /// <see cref="Execute"/>を実行したときに, ここで指定した処理が実行される. /// 実行する処理が無い場合は, nullを指定する</param> public Transition(State nextState, TransitionMethodDelegate transitionMethod) { if (nextState == null) { throw new NotImplementedException(); } NextState = nextState; TransitionMethod = transitionMethod; }
private void GeroMachineSampleForm_Load(object sender, EventArgs e) { AllTriggers = new Trigger[3] { new Trigger(), new Trigger(), new Trigger() }; State[] all_states = new State[3] { new NormalState(AllTriggers), new NormalState(AllTriggers), new NormalState(AllTriggers) }; all_states[0].StateName = "State 1"; all_states[1].StateName = "State 2"; all_states[2].StateName = "State 3"; var matrixData = new Dictionary<State, Dictionary<Trigger, ITransition>> { { all_states[0], new Dictionary<Trigger, ITransition> { { AllTriggers[0], new Transition(all_states[1], null) }, { AllTriggers[1], new Transition(all_states[2], null) }, } }, { all_states[1], new Dictionary<Trigger, ITransition> { { AllTriggers[0], new Transition(all_states[2], null) }, { AllTriggers[1], new Transition(all_states[2], null) }, { AllTriggers[2], new Transition(all_states[0], null) } } }, { all_states[2], new Dictionary<Trigger, ITransition> { { AllTriggers[0], new Transition(all_states[2], null) }, { AllTriggers[2], new Transition(all_states[0], null) } } } }; TransitionMatrix transitino_matrix = new TransitionMatrix(matrixData); MainStateMachine = new StateMachine(all_states[0], transitino_matrix); CurrentStateNameLabel.Text = MainStateMachine.CurrentStateName; }
/// <summary> /// 初期状態と状態遷移表を指定し, /// <see cref="StateMachine"/>クラスのインスタンスを初期化する. /// </summary> /// <param name="initialState">初期状態</param> /// <param name="matrixData">状態遷移表</param> /// <exception cref="ArgumentNullException">引数<paramref name="initialState"/>がnull, /// または引数<paramref name="matrixData"/>がnull.</exception> public StateMachine(State initialState, ITransitionMatrix matrixData) { if (initialState == null) { throw new ArgumentNullException("initialState"); } if (matrixData == null) { throw new ArgumentNullException("matrixData"); } CurrentState = initialState; TransitionMatrixData = matrixData; }
public void TestConstructor(State setting_NextState, State expected_NextState, Transition.TransitionMethodDelegate setting_TransitionMethod, Transition.TransitionMethodDelegate expected_TransitionMethod) { // Execute Transition transition = new Transition(setting_NextState, setting_TransitionMethod); // Get result Type type = typeof(Transition); FieldInfo field_info = type.GetField("NextState", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance); State actual_NextState = (State)field_info.GetValue(transition); field_info = type.GetField("TransitionMethod", BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Instance); var actual_TransitionMethod = (Transition.TransitionMethodDelegate)field_info.GetValue(transition); // Validate Assert.Equal(expected_NextState, actual_NextState); Assert.Equal(expected_TransitionMethod, actual_TransitionMethod); }
/// <summary> /// 状態が<paramref name="currentState"/>のときにトリガ<paramref name="trigger"/>が発生した場合の, /// 起こる遷移を取得する. /// </summary> /// <param name="currentState">現在の状態</param> /// <param name="trigger">発生したトリガ</param> /// <returns><paramref name="currentState"/>で<paramref name="trigger"/>が発生したときに起こる遷移. /// 起こる遷移が無ければ, nullが返る.</returns> /// <exception cref="ArgumentNullException">引数<paramref name="currentState"/>がnull, /// または引数<paramref name="trigger"/>がnull.</exception> /// <exception cref="ArgumentOutOfRangeException">引数<paramref name="currentState"/>が, /// 状態遷移表に存在しない.</exception> public ITransition SearchTransition(State currentState, Trigger trigger) { if (currentState == null) { throw new ArgumentNullException("currentState"); } if (trigger == null) { throw new ArgumentNullException("trigger"); } if (MatrixData.ContainsKey(currentState) == false) { throw new ArgumentOutOfRangeException("currentState"); } if (MatrixData[currentState].ContainsKey(trigger)) { return MatrixData[currentState][trigger]; } return null; }
/// <summary> /// このステートマシンにトリガーを入力する /// </summary> /// <remarks> /// ステートマシンにトリガーを入力すると, /// このステートマシンが持っている状態遷移表に従って遷移が発生し, /// 現在の状態が遷移後の状態に更新される. /// トリガーに対する遷移が定義されていない場合は, 何もしない. /// </remarks> /// <param name="trigger">入力するトリガー</param> /// <exception cref="ArgumentNullException">引数<paramref name="trigger"/>がnull.</exception> /// <exception cref="InvalidOperationException">現在の状態が状態遷移表に存在しない. /// 状態遷移表の設定ミスなどによる.</exception> public void InputTrigger(Trigger trigger) { if (trigger == null) { throw new ArgumentNullException("trigger"); } System.Diagnostics.Debug.Assert(CurrentState != null); ITransition transition; try { transition = TransitionMatrixData.SearchTransition(CurrentState, trigger); } catch (ArgumentOutOfRangeException e) { throw new InvalidOperationException("現在の状態は, 状態遷移表に登録されていません.", e); } if (transition != null) { CurrentState = transition.Execute(); } }
public void TestNullParameter(State setting_NextState, Transition.TransitionMethodDelegate setting_TransitionMethod) { // Execute, Validate Assert.Throws<NotImplementedException>(() => new Transition(setting_NextState, setting_TransitionMethod)); }
public RegularInstanceTest() { calledFlag = false; setting_NextState = new NormalState(new Trigger[1] { new Trigger() }); setting_TransitionMethod = () => { calledFlag = true; return; }; transition = new Transition(setting_NextState, setting_TransitionMethod); }
public NoTransitionMethodInstanceTest() { setting_NextState = new NormalState(new Trigger[1] { new Trigger() }); transition = new Transition(setting_NextState, null); }
public void TestConstructor() { // Prepare datas Trigger[] all_triggers = new Trigger[5] { new Trigger(), new Trigger(), new Trigger(), new Trigger(), new Trigger() }; TriggerSet1 = new Trigger[3] { all_triggers[0], all_triggers[1], all_triggers[2] }; TriggerSet2 = new Trigger[3] { all_triggers[0], all_triggers[2], all_triggers[4] }; TriggerSet3 = new Trigger[3] { all_triggers[2], all_triggers[3], all_triggers[4] }; State[] states = new State[3] { new NormalState(TriggerSet1), new NormalState(TriggerSet2), new NormalState(TriggerSet3) }; var input_transitionMatrix = new Dictionary<State, Dictionary<Trigger, ITransition>>() { { states[0], new Dictionary<Trigger, ITransition>() { { TriggerSet1[0], new Transition(states[2], null) }, { TriggerSet1[1], new Transition(states[2], null) }, { TriggerSet1[2], new Transition(states[1], null) } } }, { states[1], new Dictionary<Trigger, ITransition>() { { TriggerSet2[0], new Transition(states[0], null) }, { TriggerSet2[1], new Transition(states[1], null) }, { TriggerSet2[2], new Transition(states[2], null) } } }, { states[2], new Dictionary<Trigger, ITransition>() { { TriggerSet3[0], new Transition(states[2], null) }, { TriggerSet3[1], new Transition(states[2], null) }, { TriggerSet3[2], new Transition(states[0], null) } } } }; var expected_MatrixData = new Dictionary<State, Dictionary<Trigger, ITransition>>(input_transitionMatrix); // Execute TransitionMatrix transition_matrix = new TransitionMatrix(input_transitionMatrix); // Get result FieldInfo field_info = transition_matrix.GetType().GetField("MatrixData", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance); var actual_MatrixData = (Dictionary<State, Dictionary<Trigger, ITransition>>)field_info.GetValue(transition_matrix); // Validate Assert.Same(input_transitionMatrix, actual_MatrixData); Assert.Equal(expected_MatrixData, actual_MatrixData); }