2009-04-16 9 views
124

ho una classe di base che contiene i seguenti eventi:C#: generazione di un evento ereditato

public event EventHandler Loading; 
public event EventHandler Finished; 

in una classe che eredita da questa classe di base provo a generare l'evento:

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

ricevo il seguente errore:

l'evento 'BaseClass.Loading' possono essere visualizzati solo sul lato sinistro del + = o - = (BaseClass')

Suppongo che non possa accedere a questi eventi come gli altri membri ereditati?

risposta

138

Quello che devi fare, è questo:

Nella classe di base (in cui è stato dichiarato gli eventi), creare metodi protetti che possono essere usati per aumentare gli eventi:

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

(nota che probabilmente dovresti cambiare quei metodi ods, al fine di verificare se è necessario richiamare o meno l'eventhandler).

Poi, in classi che ereditano da questa classe di base, si può semplicemente chiamare i metodi OnFinished o OnLoading per sollevare gli eventi:

public AnotherClass : MyClass 
{ 
    public void DoSomeStuff() 
    { 
     ... 
     OnLoading(EventArgs.Empty); 
     ... 
     OnFinished(EventArgs.Empty); 
    } 
} 
+5

Tali metodi dovrebbero essere protetti virtuale a meno che non ci sia una ragione per fare altrimenti. –

+6

Perché dovrebbe essere virtuale? Lo dichiarerei virtuale se volessi che gli eredi cambino il modo in cui l'evento dovrebbe essere sollevato, ma la maggior parte delle volte non vedo alcun motivo per farlo ... –

+0

Secondo le linee guida Microsoft dice che dovrebbe essere virtuale in modo che gli ereditari possano controllare il evento .. inoltre il metodo On protetto dovrebbe accettare gli event arg, non crearli autonomamente. Questa risposta è sbagliata rispetto a quella corretta di Adam Robinson. – meandmycode

7

I am assuming I cannot access these events the same as other inherited members?

Precisamente. È consuetudine fornire una funzione protetta OnXyz o RaiseXyz per ciascun evento nella classe base per abilitare l'attivazione da classi ereditate. Per esempio:

public event EventHandler Loading; 

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

Chiamato nella classe ereditata:

OnLoading(); 
111

È possibile accedere solo un evento nella classe di dichiarare, come .NET crea variabili di istanza private dietro le quinte che effettivamente detengono il delegato. Facendo questo ..

public event EventHandler MyPropertyChanged; 

in questo modo;

private EventHandler myPropertyChangedDelegate; 

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

e fare questo ...

MyPropertyChanged(this, EventArgs.Empty); 

è in realtà questo ...

myPropertyChangedDelegate(this, EventArgs.Empty); 

in modo da poter (ovviamente) accedere solo la variabile di istanza delegato privato da all'interno del dichiarare classe.

La convenzione è quello di fornire qualcosa di simile nella classe dichiarando ..

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

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

È quindi possibile chiamare OnMyPropertyChanged(EventArgs.Empty) da qualsiasi luogo in quella classe o sotto la gerarchia di ereditarietà per richiamare l'evento.

+0

Ho avuto alcuni problemi nell'implementare questo ... http://stackoverflow.com/q/10593632/328397 – LamonteCristo

-1

Si può provare in questo modo, per me funziona:

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); 
    } 
} 
+2

Nota che questo articolo mette in guardia dichiarare eventi virtuali e sovrascriverli in quanto afferma che il compilatore non gestisce correttamente questo: https://msdn.microsoft.com/en-us/library/hy3sefw3.aspx –