对某些KeyPress序列使用Reactive Extension?

时间:2010-08-17 09:29:16

标签: c# .net events system.reactive

我是新的..或者更确切地说......从未使用过RX,所以我想知道我是否可以在这种情况下使用它:我想在我的应用程序中添加一种Resharper Live Templates功能,允许用户输入短序列字符后跟一个[Tab],我的应用程序将用其他指定的全文替换以前键入的字符。

现在我有一个字符数组列表,每个字符数组代表一个可能的序列。我想要某种断言/ -keys来打破链条(例如空间)。 我在我的应用程序中的每个KeyPress上都有一个事件,现在(如何)我可以使用RX观察此事件并检查上述列表是否已经完成了其中一个序列并最终按下了[Tab]? / p>

1 个答案:

答案 0 :(得分:3)

我不知道是否为时已晚,但我有一个答案。

您需要使用的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

享受!