用c#对事件进行分组

本文关键字:事件 | 更新日期: 2023-09-27 18:14:48

是否有现成的解决方案来对事件进行分组?

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

类似:组事件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没有

用c#对事件进行分组

你可以使用响应式扩展。

看看Observable。FromEvent(或observable . fromeventpattern)方法将标准的。net事件转换为可观察对象,然后你可以使用observable . combinellatest对结果进行分组。

下面是一个伪代码:

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

当两个事件都被触发时,生成的可观察对象才会被触发。

编辑

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扩展为您的情况,但我找不到它。

我认为响应式扩展可能是最接近你正在寻找的。它提供了将事件转换为可观察对象的帮助器,以及可以用来组合这些可观察对象的linq风格语法。

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

<>之前公共类TwoEventGroup{private bool _eventAFired;private bool _eventBFired;EventAHandler(){_eventAFired = true;TestAndFire ();}EventBHandler(){_eventBFired = true;TestAndFire ();}private void TestAndFire(){if (_eventAFired && _eventBFired){_eventAFired = false;_eventBFired = false;if (GroupEvent != null)GroupEvent ();}}公共事件Action GroupEvent;}之前

这只是一个概念上的实现,你可能想把事件委托作为一个通用的,扩展到n个事件而不是仅仅两个,(也许)处理事件触发之间的超时,考虑这个类将如何扩展(如果有的话),等等。

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