2009-04-03 1 views
4

J'ai eu une fois une situation où j'ai dû remplacer le gestionnaire d'événements dans une classe dérivée de la mienne. Je ne pouvais malheureusement pas le "surcharger" car la logique d'implémentation était strictement liée à l'implémentation de cette méthode particulière dans la classe de base.Comment "dissocier" un gestionnaire d'événements attaché à un événement dans la classe de base lorsque je suis dans une classe dérivée?

Mon idée naturelle était d'abord de "délier" le gestionnaire d'événements original de l'événement, puis de lier ma propre méthode. J'ai donc essayé d'utiliser le « - = » opérateur comme:

myObject.SomeEvent -= new EventHandler (BaseClass.SomeEventHandler) 

à quel point le râleuse du compilateur qu'il n'a pas eu accès à la méthode privée SomeEventHandler. Comme la classe de base faisait partie de la bibliothèque, je ne voulais pas vraiment modifier sa mise en œuvre (bien que cela paraisse juste en changeant "private" en "protected");

Il est si simple d'attacher un gestionnaire d'événements à un événement. Pourquoi est-il si difficile de s'en débarrasser?

Pourquoi je le voulais? Parce que la mise en œuvre de base posait des problèmes (ne gérait pas notre cas particulier), je voulais donc le redéfinir. Mais même après avoir attaché mon gestionnaire d'événements, l'implémentation de base était de toute façon exécutée. Puisqu'il effectuait une sorte de redirection, ma propre implémentation ne serait jamais exécutée puisque le traitement de la demande était cassé au serveur après la redirection.

Est-il possible de se débarrasser d'un gestionnaire d'événements dans une classe de base à partir d'une bibliothèque sans modifier son implémentation?

Répondre

5

Il serait être tout aussi facile de se débarrasser du gestionnaire si votre code peut voir officiellement le gestionnaire. Si cela est absolument nécessaire, il est possible de se désabonner en utilisant la réflexion pour obtenir le délégué, mais c'est désordonné. Il serait un lot plus propre et plus sûr à un: soit éviter l'exigence, ou b: changer le code pour rendre le gestionnaire protected.


Approche par réflexion (utilisation à risque); décommentez le bloc dans le Bar.ctor() pour voir la modification.

using System; 
class Foo 
{ 
    public event EventHandler SomeEvent; 
    public Foo() 
    { 
     SomeEvent += SecretHandler; // a bad idea, anyway 
            //(self-subscribed events....) 
    } 
    protected virtual void OnSomeEvent() 
    { 
     EventHandler handler = SomeEvent; 
     if (handler != null) handler(this, EventArgs.Empty); 
    } 
    private void SecretHandler(object sender, EventArgs args) 
    { 
     Console.WriteLine("suscribed"); 
    } 
} 
class Bar : Foo 
{ 
    public Bar() 
    { 
     /* 
     MethodInfo method = typeof(Foo).GetMethod("SecretHandler", 
      BindingFlags.NonPublic | BindingFlags.Instance); 
     EventHandler handler = (EventHandler)Delegate.CreateDelegate(
      typeof(EventHandler), this, method); 
     SomeEvent -= handler; 
     */ 
    } 
    public void Test() 
    { 
     OnSomeEvent(); 
    } 
} 
static class Program 
{ 
    static void Main() 
    { 
     Bar bar = new Bar(); 
     bar.Test(); 
    } 
} 
+0

Y a-t-il un moyen de se débarrasser de tous les gestionnaires attachés sans y avoir accès? Juste laisser le système secrètement de vous identifier et les dissocier tous? – User

+0

Serez-vous assez aimable pour montrer comment le faire en utilisant la réflexion? – User

Questions connexes