2009-04-16 20 views
124

tengo una clase base que contiene los siguientes eventos:C#: provoca un evento heredado

public event EventHandler Loading; 
public event EventHandler Finished; 

en una clase que hereda de esta clase base trato de provocar el evento:

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

recibo el siguiente error:

el evento 'BaseClass.Loading' sólo puede aparecer en el lado izquierdo de + = o - = (BaseClass')

Supongo que no puedo acceder a estos eventos de la misma manera que a otros miembros heredados.

Respuesta

138

Lo que tienes que hacer, es la siguiente:

En su clase base (en la que han declarado los acontecimientos), crear métodos protegidos que pueden ser utilizados para elevar los eventos:

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

(Tenga en cuenta que probablemente debería cambiar los metanfetamina ods, para comprobar si debe invocar el manejador de eventos o no).

Luego, en las clases que heredan de esta clase base, sólo puede llamar a los métodos OnFinished o onloading para elevar los eventos:

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

Estos métodos deben ser protegidos virtuales a menos que haya alguna razón para no hacerlo. –

+6

¿Por qué debería ser virtual? Lo declararía virtual si quisiera que los herederos cambien la forma en que se debe plantear el evento, pero la mayoría de las veces, no veo ninguna razón para hacerlo ... –

+0

Según las directrices, Microsoft dice que debe ser virtual para que los herederos puedan controlar el evento ... además, el método protegido On debería tomar eventos args, no crearlos por sí mismo. Esta respuesta es incorrecta en comparación con la correcta por Adam Robinson. – meandmycode

7

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

Precisamente. Es costumbre proporcionar una función protegida OnXyz o RaiseXyz para cada evento en la clase base para habilitar el aumento desde las clases heredadas. Por ejemplo:

public event EventHandler Loading; 

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

Llamado en la clase heredada:

OnLoading(); 
111

Sólo se puede acceder a un evento en la clase que declara, como .NET crea variables de instancia privadas detrás de las escenas que realmente mantienen al delegado. Haciendo esto ...

public event EventHandler MyPropertyChanged; 

está haciendo esto;

private EventHandler myPropertyChangedDelegate; 

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

y haciendo esto ...

MyPropertyChanged(this, EventArgs.Empty); 

es en realidad este ...

myPropertyChangedDelegate(this, EventArgs.Empty); 

Así que (obviamente) sólo se accede a la variable de instancia privada delegado desde dentro de la que se declara clase.

La convención es proporcionar algo como esto en la clase declarando ..

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

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

A continuación, puede llamar OnMyPropertyChanged(EventArgs.Empty) desde cualquier punto de esa clase o por debajo de la jerarquía de herencia para distribuir el evento.

+0

Tuve algunos problemas al implementar esto ... http://stackoverflow.com/q/10593632/328397 – LamonteCristo

-1

Usted puede tratar de esta manera, funciona para mí:

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

Tenga en cuenta que este artículo advierte contra declarar eventos virtuales y anularlos ya que afirma que el compilador no maneja esto correctamente: https://msdn.microsoft.com/en-us/library/hy3sefw3.aspx –

Cuestiones relacionadas