2009-04-16 13 views
124

Mam klasy bazowej, która zawiera następujące zdarzenia:C#: Podnoszenie odziedziczony zdarzenie

public event EventHandler Loading; 
public event EventHandler Finished; 

w klasie, która dziedziczy z tej klasy bazowej próbuję podnieść zdarzenie:

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

I pojawia się następujący błąd:

zdarzenie „BaseClass.Loading” może pojawić się tylko po stronie lewej lub + = - = (klasy bazowej)

Zakładam, że nie mogę uzyskać dostępu do tych wydarzeń tak samo jak inni dziedziczeni członkowie?

Odpowiedz

138

Co trzeba zrobić, to:

w klasie bazowej (w którym został ogłoszony zdarzenia), należy utworzyć chronione metody, które można wykorzystać do zwiększenia liczby zdarzeń:

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

(Należy pamiętać, że prawdopodobnie należy zmienić te metody ods, aby sprawdzić, czy musisz wywołać moduł obsługi zdarzenia, czy nie).

Następnie w klasach dziedziczących z tej klasy bazowej, można po prostu zadzwonić do OnFinished lub OnLoading metod, aby podnieść zdarzenia:

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

Metody te powinny być chronione wirtualne chyba że istnieje jakiś powód, aby zrobić inaczej. –

+6

Dlaczego powinien być wirtualny? Powiedziałbym, że jest to wirtualne, jeśli chciałbym, aby spadkobiercy zmienili sposób, w jaki wydarzenie powinno zostać podniesione, ale w większości przypadków nie widzę powodu, aby to robić ... –

+0

Według wytycznych Microsoft powinno być wirtualne, aby dziedziczenie mogło kontrolować event .. dodatkowo metoda On protected powinna brać argumenty zdarzeń, a nie tworzyć ich samodzielnie. Ta odpowiedź jest błędna w porównaniu z poprawną przez Adama Robinsona. – meandmycode

7

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

Precyzyjnie. Zwyczajem jest dostarczanie chronionej funkcji OnXyz lub RaiseXyz dla każdego zdarzenia w klasie bazowej, aby umożliwić podnoszenie z dziedziczonych klas. Na przykład:

public event EventHandler Loading; 

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

Powołani w dziedziczonej klasy:

OnLoading(); 
111

można uzyskać dostęp tylko zdarzenia w klasie stwierdzającej, jak .NET tworzy prywatne instancje za kulisami, które faktycznie przechowują delegata. Robiąc to ..

public event EventHandler MyPropertyChanged; 

faktycznie to robi;

private EventHandler myPropertyChangedDelegate; 

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

i robi to ...

MyPropertyChanged(this, EventArgs.Empty); 

jest faktycznie to ...

myPropertyChangedDelegate(this, EventArgs.Empty); 

Więc można (oczywiście) tylko dostęp zmiennej instancji delegat prywatny od obrębie deklarowania klasa.

Konwencja jest dostarczenie czegoś takiego w klasie uznającej ..

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

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

Można połączyć OnMyPropertyChanged(EventArgs.Empty) z dowolnego miejsca w tej klasie lub poniżej heirarchy spadków do wywołania zdarzenia.

+0

Miałem pewne problemy z implementacją tego ... http://stackoverflow.com/q/10593632/328397 – LamonteCristo

-1

można spróbować w ten sposób, to działa na mnie:

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

Zauważ, że ten artykuł ostrzega przed deklarowanie zdarzeń wirtualnych i przesłonięcie ich, ponieważ twierdzi, że kompilator nie obsługuje tego poprawnie: https://msdn.microsoft.com/en-us/library/hy3sefw3.aspx –

Powiązane problemy