6 votes

regroupement d'événements en C#

Existe-t-il une solution prête à l'emploi pour les événements de groupe ?

Disons que j'ai deux événements : A et B. Je veux qu'une méthode M soit exécutée lorsque A et B ont été déclenchés. Il n'est pas nécessaire qu'ils se déclenchent exactement au même moment.

Quelque chose comme : L'événement de groupe G se déclenche après que A et B se soient déclenchés. Je dois enregistrer la méthode M uniquement pour l'événement de groupe G.

A peut tirer plus d'une fois, G ne tirera qu'après que B ait tiré. De même dans l'autre sens.

Je cherche une bibliothèque qui organise ces événements.

Edit : Exemple

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 signifie que l'événement se déclenche, 0 ce n'est pas le cas.

7voto

Davide Icardi Points 2215

Vous pouvez utiliser Extensions réactives .

Regardez le Observable.FromEvent (ou Observable.FromEventPattern) pour convertir un événement .NET standard en observable, puis vous pouvez regrouper les résultats à l'aide des méthodes suivantes Observable.CombineLatest .

Voici un pseudo-code :

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

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

L'observable généré est déclenché lorsque les deux événements sont déclenchés.

EDIT

CombineLatest produire une sortie avec les derniers résultats, sans remettre son état à zéro. Donc par exemple si A1 est tiré puis B1 est tiré G1 est produit avec (A1 + B1), mais si B2 est tiré alors G2 est produit avec (A1 + B2) et ainsi de suite...

Pour produire exactement les résultats attendus, vous pouvez écrire quelque chose comme :

    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");
    //}

En gros, je vérifie si les derniers résultats sont différents du résultat actuel. Peut-être existe-t-il une extension native de RX pour votre cas mais je ne la trouve pas.

3voto

spender Points 51307

Je pense que Extensions réactives est probablement le plus proche de ce que vous recherchez. Il fournit des aides pour transformer les événements en observables, et une syntaxe de style linq que vous pouvez utiliser pour composer ces observables.

1voto

Eli Algranti Points 3284

Vous pouvez écrire une telle classe vous-même. Voici une implémentation (très) triviale :

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;
}

Il s'agit juste d'une implémentation conceptuelle, vous voudrez probablement avoir le délégué d'événement comme un générique, l'étendre à n événements au lieu de seulement deux, (peut-être) gérer les délais entre les déclenchements d'événements, penser à la façon dont cette classe sera étendue (si elle l'est), etc.

La suggestion de Rx faite par @spender est intéressante (+1) mais la bibliothèque est orientée vers les événements asynchrones et sa courbe d'apprentissage est un peu raide. Cela pourrait être excessif si vous ne voulez que des groupements simples d'événements connus, ou des événements du même type, et non quelque chose d'entièrement générique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X