2010-08-17 50 views
2

我是新的......或者更确切地说......从来没有使用过RX,所以我想知道我是否可以将它用于这种情况:我想为我的应用添加一种Resharper Live Templates功能,允许用户输入短序列字符后面跟着一个[Tab],我的应用程序将用其他指定的全文替换先前输入的字符。对某些KeyPress序列使用Reactive Extension?

现在我有一个字符数组的列表,每个字符数组代表一个可能的序列。我想要某种停止词/关键词(例如空格)。 我的应用程序中的每个KeyPress上都有一个事件,现在我可以如何使用RX来观察这个事件,并检查上述列表是否已完成一个序列并最终[Tab]被按下?

回答

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 

享受!

+0

太棒了!谢谢! – 2010-12-08 13:15:51

相关问题