【问题标题】:grouping events in C#C#中的事件分组
【发布时间】:2013-05-21 22:39:16
【问题描述】:

有没有现成的解决方案来分组事件?

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

类似: 组事件 G 在 A 和 B 都触发后触发。我只需要在Group event 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它没有。

【问题讨论】:

  • 不知道这样的事情,但是如果你说 a,a,a,b,b 被解雇了,在这种情况下 g 应该被解雇多少次?
  • 或者您是否在您的代码中保证 A 和 B 只针对给定实例触发一次?更多细节真的很有帮助。

标签: c# events


【解决方案1】:

您可以使用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 扩展,但我找不到它。

【讨论】:

    【解决方案2】:

    我认为Reactive Extensions 可能最接近您要查找的内容。它提供了将事件转换为可观察对象的帮助程序,以及可用于组合这些可观察对象的 linq 样式语法。

    【讨论】:

      【解决方案3】:

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

      公共类 TwoEventGroup { 私人布尔_eventAFired; 私人布尔_eventBFired; 公共无效事件处理程序() { _eventAFired = true; 测试和火(); } 公共无效事件BHandler() { _eventBFired = true; 测试和火(); } 私人无效TestAndFire() { 如果(_eventAFired && _eventBFired) { _eventAFired = 假; _eventBFired = false; 如果(组事件!= null) 组事件(); } } 公共事件 Action GroupEvent; }

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多