Как получить последнее известное значение IObservable?

Предположим, я создаю редактор изображений с помощью Rx.Net. Пользователь может управлять холстом с помощью мыши. Применяемая манипуляция зависит от выбранного в данный момент инструмента. Например, может быть инструмент «рисовать» и инструмент «стирать». Одновременно может быть выбран только один инструмент.

У меня есть три потока; один для событий мыши; один для команд, выдаваемых щелчком мыши; и еще один для выбора инструментов:

IObservable<ITool> toolSelection;
IObservalbe<MouseState> mouse;
IObservable<ICommand> commands;

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

Теперь я мог бы сохранить последний выбранный инструмент в переменной следующим образом:

var selectedTool = defaultTool;
toolSelection.Subscribe(x => selectedTool = x);

Я могу использовать selectedTool для создания потока commands:

var commands = mouse.Select(x => selectedTool.CreateCommand(x));

Однако это не похоже на «реактивный» способ ведения дел. Могу ли я достичь той же логики, используя композиции потоков?

Я просмотрел CombineLatest, но он вызывает генерацию нежелательных событий, когда пользователь переключает инструмент. Я хочу, чтобы команды выдавались только тогда, когда пользователь щелкает.


person sdgfsdh    schedule 06.07.2016    source источник


Ответы (1)


Похоже, вам нужно .Switch().

Попробуйте этот код:

IObservable<ICommand> commands =
    toolSelection
        .Select(t => mouse.Select(m => t.CreateCommand(m)))
        .Switch();

Метод расширения .Switch() берет, в данном случае, IObservable<IObservable<ICommand>> и превращает его в IObservable<ICommand>, беря последнюю наблюдаемую, созданную внешней наблюдаемой, и производя только значения из нее, и удаляя предыдущие.

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

person Enigmativity    schedule 07.07.2016