public class KeyUpper {
Func<Key, bool> _evaluate;
public void RegisterEvaluator(Func<Key, bool> evaluate){
_evaluate = evaluate;
}
public void KeyUp(object sender, KeyEventArgs e){
if (_evaluate(e.KeyCode))
SomeResponse();
}
public void SomeResponse(){
// ...
}
}
keyUpper.RegisterEvaluator(key =>
{
if (key == Key.A)
if (key == Key.W)
if (key == Key.A)
return true;
}
);
key
参数提供一系列评估,期望每个评估行都在等待,以便在一系列1的密钥事件序列之后调用SomeResponse():A 2:W 3 :A key == Key.W
永远不会成为现实答案 0 :(得分:2)
如果异步性不是一个要求,你可以通过一个几乎总是等待的线程来完成它,你可以通过给lambda一些阻塞方式来访问密钥。例如:
public void RegisterEvaluator(Func<Func<Key>, bool> evaluate);
…
keyUpper.RegisterEvaluator(
getKey => getKey() == Key.A && getKey() == Key.W);
然后 RegisterEvaluator
将启动一个在循环中调用lambda的新线程,向其传递一个访问密钥的方法,如果当前没有密钥可用,则阻塞,例如使用BlockingCollection<Key>
如果您认为这样做是浪费(确实如此),并且您可以使用async-await,只需创建lambda async
并将传入的方法更改为异步方法:
public Task RegisterEvaluator(Func<Func<Task<Key>>, Task<bool>> evaluate);
…
keyUpper.RegisterEvaluator(
async getKey => await getKey() == Key.A && await getKey() == Key.W);
后一版本的实现(使用BlockBuffer<Key>
)可能如下所示:
class KeyUpper
{
private readonly BufferBlock<Key> m_keyBuffer = new BufferBlock<Key>();
public async Task RegisterEvaluator(
Func<Func<Task<Key>>, Task<bool>> evaluate)
{
while (true)
{
if (await evaluate(m_keyBuffer.ReceiveAsync))
SomeResponse();
}
}
public void KeyUp(object sender, KeyEventArgs e)
{
m_keyBuffer.Post(e.Key);
}
private void SomeResponse()
{
// whatever
}
}
现在,我不确定你想要如何处理匹配键,但我认为它不是这样的。例如,此示例代码将匹配键BAW
的序列,但不匹配AAW
。
另一种选择是不使用Func<Task<Key>>
,但您的自定义等待可以等待多次,每次执行时都会给出一个键:
public Task RegisterEvaluator(Func<KeyAwaitable, Task<bool>> evaluate);
…
keyUpper.RegisterEvaluator(
async getKey => await getKey == Key.A && await getKey == Key.W);
但我认为以这种方式这样做会更加困惑和困难。