web-dev-qa-db-fra.com

C #: levée d'un événement hérité

J'ai une classe de base qui contient les événements suivants:

public event EventHandler Loading;
public event EventHandler Finished;

Dans une classe qui hérite de cette classe de base, j'essaie de déclencher l'événement:

this.Loading(this, new EventHandler()); // All we care about is which object is loading.

Je reçois l'erreur suivante:

L'événement 'BaseClass.Loading' ne peut apparaître que sur le côté gauche de + = ou - = (BaseClass ')

Je suppose que je ne peux pas accéder à ces événements de la même manière que les autres membres hérités?

133
jwarzech

Ce que vous devez faire, c'est ceci:

Dans votre classe de base (où vous avez déclaré les événements), créez des méthodes protégées pouvant être utilisées pour déclencher les événements:

public class MyClass
{
   public event EventHandler Loading;
   public event EventHandler Finished;

   protected virtual void OnLoading(EventArgs e)
   {
       EventHandler handler = Loading;
       if( handler != null )
       {
           handler(this, e);
       }
   }

   protected virtual void OnFinished(EventArgs e)
   {
       EventHandler handler = Finished;
       if( handler != null )
       {
           handler(this, e);
       }
   }
}

(Notez que vous devriez probablement changer ces méthodes, afin de vérifier si vous devez invoquer le gestionnaire d'événements ou non).

Ensuite, dans les classes qui héritent de cette classe de base, vous pouvez simplement appeler les méthodes OnFinished ou OnLoading pour déclencher les événements:

public AnotherClass : MyClass
{
    public void DoSomeStuff()
    {
        ...
        OnLoading(EventArgs.Empty);
        ...
        OnFinished(EventArgs.Empty);
    }
}
146
Frederik Gheysels

Vous ne pouvez accéder à un événement que dans la classe déclarante, car .NET crée des variables d'instance privées dans les coulisses qui contiennent le délégué. Ce faisant..

public event EventHandler MyPropertyChanged;

fait réellement ceci;

private EventHandler myPropertyChangedDelegate;

public event EventHandler MyPropertyChanged
{
    add { myPropertyChangedDelegate += value; }
    remove { myPropertyChangedDelegate -= value; }
}

et faire ça ...

MyPropertyChanged(this, EventArgs.Empty);

est-ce réellement ...

myPropertyChangedDelegate(this, EventArgs.Empty);

Ainsi, vous ne pouvez (évidemment) accéder qu’à la variable d’instance de délégué privé à partir de la classe déclarante.

La convention est de fournir quelque chose comme ceci dans la classe déclarante.

protected virtual void OnMyPropertyChanged(EventArgs e)
{
    EventHandler invoker = MyPropertyChanged;

    if(invoker != null) invoker(this, e);
}

Vous pouvez ensuite appeler OnMyPropertyChanged(EventArgs.Empty) de n'importe où dans cette classe ou en dessous de la hiérarchie d'héritage pour appeler l'événement.

116
Adam Robinson

Je suppose que je ne peux pas accéder à ces événements de la même manière que les autres membres hérités?

Précisément. Il est habituel de fournir une fonction protégée OnXyz ou RaiseXyz pour chaque événement de la classe de base afin de permettre la levée à partir de classes héritées. Par exemple:

public event EventHandler Loading;

protected virtual void OnLoading() {
    EventHandler handler = Loading;
    if (handler != null)
        handler(this, EventArgs.Empty);
}

Appelé dans la classe héritée:

OnLoading();
8
Konrad Rudolph

Vous pouvez essayer de cette façon, cela fonctionne pour moi:

public delegate void MyEventHaldler(object sender, EventArgs e);

public class B
{
    public virtual event MyEventHaldler MyEvent;
    protected override void OnChanged(EventArgs e)
    {
        if (MyEvent != null)
            MyEvent(this, e);
    }
}

public class D : B
{
    public override event MyEventHaldler MyEvent;
    protected override void OnChanged(EventArgs e)
    {
        if (MyEvent != null)
            MyEvent(this, e);
    }
}
0

ne pas ressusciter un vieux fil, mais au cas où quelqu'un regarderait, ce que j'ai fait était 

protected EventHandler myPropertyChangedDelegate;

public event EventHandler MyPropertyChanged
{
    add { myPropertyChangedDelegate += value; }
    remove { myPropertyChangedDelegate -= value; }
}

Cela vous permet d'hériter de l'événement dans une classe dérivée afin de pouvoir l'invoquer sans avoir à emballer la méthode tout en conservant la syntaxe + =. Je suppose que vous pouvez toujours le faire avec les méthodes d’emballage si vous le faisiez. 

public event EventHandler MyPropertyChanged
{
   add { AddDelegate(value); }
   remove { RemoveDelegate(value); }
}
0
Zeraphil