6

是否有任何现成的解决方案来分组活动?

假设我有两个事件:A 和 B。我希望在 A 和 B 被触发时执行方法 M,它们不需要同时触发。

类似于:组事件 G 在 A 和 B 都触发后触发。我只需要在组事件 G 中注册方法 M。

A可以开火不止一次,G只有在B开火后才会开火。其他方式也一样。

我正在寻找一个有这些事件的图书馆。

编辑:示例

Events:
    A | B | G
1   F   0   0
2   0   F   F
3   0   F   0 
4   0   F   0 
5   0   F   0 
6   F   0   F
7   F   0   0
8   0   F   F
9   0   0   0 
10  F   F   F

F表示事件触发, 0表示不触发。

4

3 回答 3

7

您可以使用反应式扩展

查看Observable.FromEvent(或 Observable.FromEventPattern)方法将标准 .NET 事件转换为 observable,然后您可以使用Observable.CombineLatest对结果进行分组。

这是一个伪代码:

var observableA = Observable.FromEvent(yourEventA);
var observableB = Observable.FromEvent(yourEventB);

var observableG = observableA.CombineLatest(observableB, ...)

当两个事件都被触发时,就会触发生成的 observable。

编辑

CombineLatest生成具有最新结果的输出,而不重置其状态。因此,例如,如果 A1 被触发,则 B1 被触发 G1 由 (A1 + B1) 产生,但如果 B2 被触发,则 G2 被 (A1 + B2) 产生,依此类推......

要准确产生您的预期结果,您可以编写如下内容:

    private void SetupEvents()
    {
        var observableA = Observable.FromEventPattern((e) => btA.Click += e, (e) => btA.Click -= e);
        var observableB = Observable.FromEventPattern((e) => btB.Click += e, (e) => btB.Click -= e);

        EventPattern<object> lastA = null;
        EventPattern<object> lastB = null;
        var observableG = observableA.CombineLatest(observableB, (rA, rB) =>
        {
            if (lastA == rA || lastB == rB)
                return null;

            lastA = rA;
            lastB = rB;
            return new Tuple<EventPattern<object>, EventPattern<object>>(rA, rB);
        }).Where(p => p != null);

        observableG.Subscribe(r => Trace.WriteLine("A + B"));

        // or use ToEvent to generate another standard .NET event
        //observableG.ToEvent().OnNext += GEvent;
    }

    //void GEvent(System.Reactive.EventPattern<object> obj)
    //{
    //    Trace.WriteLine("A + B");
    //}

基本上我检查最新结果是否与当前结果不同。也许您的情况有一些本机 RX 扩展,但我找不到它。

于 2013-05-21T22:53:39.417 回答
3

我认为Reactive Extensions可能最接近您正在寻找的东西。它提供了将事件转换为可观察对象的助手,以及可用于组合这些可观察对象的 linq 样式语法。

于 2013-05-21T22:43:43.477 回答
1

你可以自己写这样一个类。这是一个(非常)简单的实现:

公共类 TwoEventGroup
{
   私人布尔_eventAFired;
   私人布尔_eventBFired;

   公共无效事件处理程序()
   {
      _eventAFired = true;
      测试和火();
   }

   公共无效事件BHandler()
   {
      _eventBFired = true;
      测试和火();
   }

   私人无效TestAndFire()
   {
      如果(_eventAFired && _eventBFired)
      {
         _eventAFired = 假;
         _eventBFired = false;
         如果(组事件!= null)
           组事件();
      }
   }

   公共事件 Action GroupEvent;
}

这只是一个概念实现,您可能希望将事件委托作为泛型,将其扩展到 n 个事件而不是仅两个事件,(也许)处理事件触发之间的超时,考虑如何扩展此类(如果有的话)等。

@spender 对 Rx 的建议是值得的(+1),但该库面向异步事件,并且学习曲线有些陡峭。如果您只想要简单的已知事件分组,或者相同类型的事件而不是完全通用的事件,这可能是矫枉过正。

于 2013-05-21T23:02:23.890 回答