Не знаю, слишком ли поздно, но у меня есть для вас ответ.
Нужно использовать метод расширения Rx BufferWithCount
.
Я предполагаю, что вы знаете, как превратить события нажатия клавиш в IObservable<char>
.
Итак, у вас есть список последовательностей символов, которые вы хотите обнаружить, а затем выполнить действие, которое я предлагаю использовать Dictionary<string, Action>
для хранения этих данных, например:
var matches = new Dictionary<string, Action>()
{
{ "ba", () => Console.WriteLine("ba") },
{ "aba", () => Console.WriteLine("aba") },
{ "baa", () => Console.WriteLine("baa") },
{ "abc\t", () => Console.WriteLine("abc\\t") },
};
Итак, вот требуемые запросы Rx (и IEnumerable
):
int max =
matches
.Select(m => m.Key.Length)
.Max();
IObservable<string> chords =
Enumerable
.Range(2, max - 1)
.Select(n => keys
.BufferWithCount(n, 1)
.Select(cs => new string(cs.ToArray())))
.Merge();
IObservable<Action> actions =
chords
.Where(s => matches.ContainsKey(s))
.Select(s => matches[s]);
Итак, наконец, у вас есть IObservable<Action>
, на который вы можете подписаться, и вы просто вызываете Action
.
Если вы хотите проверить, что это работает, используйте следующий код:
IConnectableObservable<char> keys = "ababc\tdabaababc\tebad"
.ToObservable()
.Publish();
//`.Publish()` makes a cold observable become hot,
// but you must call `Connect()` to start producing values.
//insert above `matches` definition here.
//insert above queries here.
actions.Subscribe(a => a());
keys.Connect();
Результат должен быть:
ba
aba
abc\t
ba
aba
baa
ba
aba
abc\t
ba
Наслаждайтесь!