Как передать собственный обработчик событий для прерывания в коде шаблона состояния

Я обратился к шаблону состояния для своего проекта netmf. Что-то основанное на этом: http://www.dofactory.com/Patterns/PatternState.aspx#_self2

У меня есть поворотный энкодер, который будет действовать по-разному в каждом состоянии.

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

RotaryEncoder RE = new RotaryEncoder(pin1, pin2);//create new instance of knob
RE.OnRotationEvent += OnRotationEventHandler;//subscribe to an event handler.
//do other things
...
...

static void OnRotationEventHandler(uint data1, uint data2, DateTime time)
        {
            //do something
        }

Итак, как правильно закодировать отдельные «OnRotationEventHandlers» для каждого состояния? Это часть контекста? Часть абстрактного базового класса?

Простая диаграмма состояний

Спасибо за помощь!


person GisMofx    schedule 27.03.2014    source источник
comment
Не ясно, является ли прерывание лучшим механизмом для этого. Если вы действительно хотите, чтобы прерывание управлялось напрямую, то вам, вероятно, следует сделать так, чтобы прерывание генерировало конечный автомат, чтобы он действовал. Лично, когда я делал подобные вещи, у меня был обработчик прерывания, который перехватывал события в небольшую очередь, а затем обрабатывал их асинхронно, когда у меня было время (что было довольно скоро в человеческом смысле) - это работало очень похоже на традиционную подсистему клавиатуры ПК ( и фактически принимал ввод от одного вместо ручки для эмуляции).   -  person Chris Stratton    schedule 27.03.2014
comment
@ChrisStratton Концептуально я понимаю, что вы говорите. NetMF также автоматически ставит в очередь прерывания. Я хочу, чтобы состояние реагировало на событие прерывания вращения. Прерывание может выполняться и возвращаться по часовой стрелке или против часовой стрелки. Государство должно знать, что произошло, и реагировать соответствующим образом. Например, State1 отслеживает датчик, а затем происходит вращение по часовой стрелке. Состояние 1 меняется на состояние 2. Состояния могут опрашивать флаг в цикле, но это кажется неэффективным. Я вижу и другие проблемы с этим..   -  person GisMofx    schedule 27.03.2014
comment
Вам действительно нужно делать это так сложно? Разве недостаточно просто enum с состоянием и переключателем для следующего? И вы можете реорганизовать его оттуда.   -  person Euphoric    schedule 29.03.2014
comment
@Euphoric Возможно, но я не совсем понимаю. У вас есть пример?   -  person GisMofx    schedule 30.03.2014


Ответы (1)


Я провел еще несколько исследований, и вот решение, которое я придумал:

Я использую "состояние" и "режим" взаимозаменяемо

Класс контекста:

    class ModeContext
    {
    private int rotationCount;
    private string direction;
    private State state;
    public RotaryEncoder rotaryEncoderInstance;


    public ModeContext( RotaryEncoder re)
    {
        this.State = new RPMMode(this);
        rotaryEncoderInstance = re;
        re.RotationEventHandler += OnRotationEvent;//attach to Context's Handler
        rotationCount = 0;
    }

    public State State
    {
        get { return state; }
        set { state = value; }//debug state change
    }

    //Event Handler        
    public void OnRotationEvent(uint data1, uint data2, DateTime time)
    {
        rotationCount++;
        if (data1 == 1) 
        { 
            direction = "Clockwise";
            state.OnCWRotationEvent(this);
        }
        else
        { 
            direction = "Counter-Clockwise";
            state.OnCCWRotationEvent(this);
        }
        Debug.Print(rotationCount.ToString() + ": " + direction + " Context Mode Rotation Event Fired!");
    }

Конкретный класс состояния, который наследует базовый класс состояния:

        class Mode2 : State
        {
        public override void Handle(ModeContext mode)
        {
            mode.State = new Mode2();//(mode);
        }

        public Mode2()
        {
            //do something;   
        }
        #region event handlers
        public override void OnCWRotationEvent(ModeContext mode)
        {
            mode.State = new Mode3(mode);
        }

        public override void OnCCWRotationEvent(ModeContext mode)
        {
            mode.State = new Mode1(mode);
        }
        #endregion
    }

Теперь, когда я могу изменить состояние и задать для каждого состояния конкретное управляющее поведение, куда приступить к реальной тяжелой работе?

person GisMofx    schedule 29.03.2014