在C#中分组事件

时间:2013-05-21 22:39:16

标签: c# events

是否有现成的群组活动解决方案?

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

像: 小组赛事G同时发射,A和B都被解雇。我只需要在Group事件G中注册Method 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 它没有。

3 个答案:

答案 0 :(得分:7)

您可以使用Reactive Extensions

查看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扩展,但我找不到它。

答案 1 :(得分:3)

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

答案 2 :(得分:1)

你可以自己写一堂课。这是一个(非常)微不足道的实现:

public class TwoEventGroup
{
   private bool _eventAFired;
   private bool _eventBFired;

   public void EventAHandler()
   {
      _eventAFired = true;
      TestAndFire();
   }

   public void EventBHandler()
   {
      _eventBFired = true;
      TestAndFire();
   }

   private void TestAndFire()
   {
      if (_eventAFired && _eventBFired)
      {
         _eventAFired = false;
         _eventBFired = false;
         if (GroupEvent != null)
           GroupEvent();
      }
   }

   public event Action GroupEvent;
}

这只是一个概念性实现,您可能希望将事件委托作为通用,将其扩展为n个事件而不是仅仅两个,(可能)处理事件触发之间的超时,思考如何这个课程将被扩展(如果有的话),等等。

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