2017-01-23 12 views
0

Я работаю над своим первым веб-приложением asp.net mvc. У меня есть форма, которая может быть в 14 разных состояниях и в зависимости от текущего состояния, переход к другим состояниям возможен или невозможен. Существует среднее значение 3-5 различных возможных состояний для каждого текущего состояния.Состояние машины - встроенный коммутатор

Что мне нужно сделать сейчас, это триггерные действия во время некоторого перехода состояния. В зависимости от начального состояния и конечных состояний запускаются некоторые действия (например, отправляются электронные письма).

Я начал это с помощью заявления переключателя:

switch ((int)currentState) 
     { 
      //Initial 
      case -1: 
       { 
        switch ((int)nextState) 
        { 
         //Next state: Inv. is waiting 
         case 1: 
          { 
           //Send email to x 
           emailHelper.Send(x,msg) 
           //Send email to Y 
           emailHelper.Send(y,anotherMsg) 

          } 
         case 2: 
          { 
           doSomethingelse() 
          } 
          break; 
        } 
        break; 
       } 
      //Inv is waiting 
      case 1: 
       { 
        switch ((int)nextState) 
        { 
         ... 
        } 
       } 
    ... 

Я думаю, что это решение будет работать нормально для меня, но мне интересно, если я мог бы использовать что-то предложения better..Any?

+0

Я предпочитаю иметь базовый класс 'State' или интерфейс' IState' и производный класс для каждого фактического состояния. Что-то вроде первой диаграммы [здесь] (https://www.codeproject.com/Articles/509234/The-State-Design-Pattern-vs-State-Machine). – itsme86

+0

Но действие, которое мне нужно вызвать, основано на переходе состояния, а не на фактическом состоянии –

+0

Не понимаю, почему шаблон State Design не будет работать в этом сценарии. Прочтите часть статьи о «ConcreteState» и ее обязанностях. – itsme86

ответ

1

(псевдокод)

class StateHandler 
{ 
    int CurrentState; 
    int NextState; 
    Action MyAction; 

    public void Eval(int currentState, int nextState) 
    { 
     if(currentState == this.CurrentState && nextState == this.NextState) 
     { 
      this.MyAction(); 
     } 
    } 
} 

Создание списка и заполнить его со всеми известными переходов между состояниями. Затем просто перейдите в список и вызовите Eval() для каждого элемента.

List<StateHandler> handlers = new List<StateHandler>(); 
handlers.Add(new StateHandler() 
{ 
    currentState = 0, 
    nextState = 1, 
    () => doSomeWork() 
} 
handlers.Add(new StateHandler() 
{ 
    currentState = 3, 
    nextState = 4, 
    () => doSomeOtherWork() 
} 
2

Возможно, вы можете использовать структуру данных для хранения состояний и переходов. Например, конечный автомат может быть Dictionary<int, State>, где State может быть столь же просто, как

struct State { 
    Dictionary<int, Action> transitions; 
} 

Выполнение затем переходное состояние выглядит как

var action = states[currentState].transitions[nextState]; 
action(); 
currentState = nextState; 

Конечно, это решение может быть более инкапсулируются, и мог бы использовать проверки относительно того, существует ли переход, но это является его сущностью.

2

Если производительность не является проблемой, и единственное, что вас интересует, это компактный код, рассмотрите

switch(string.Format(CultureInfo.InvariantCulture, "{0} {1}", currentState, nextState)) 
{ 
    case "-1 1": 
     //Send email to x 
     emailHelper.Send(x,msg); 
     //Send email to Y 
     emailHelper.Send(y,anotherMsg); 
     break; 
    case "-1 2": 
     doSomethingelse(); 
     break; 
    .... 
} 

Вы также можете дождаться C# 7.0 и использовать его новую форму switch statement. Что-то вроде этого:

struct State 
{ 
    int Current; 
    int Next; 
} 

.... 

State s; 
switch (s) 
{ 
    case State x when (x.Current == -1 && x.Next == 1): 
     .... 
} 
+0

Это интересная идея. –