С#: создание унаследованного события

У меня есть базовый класс, который содержит следующие события:

public event EventHandler Loading;
public event EventHandler Finished;

В классе, который наследуется от этого базового класса, я пытаюсь поднять событие:

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

Я получаю следующую ошибку:

Событие "BaseClass.Loading" может появляться только с левой стороны + = или - = (BaseClass ')

Я предполагаю, что я не могу получить доступ к этим событиям так же, как другие унаследованные элементы?

Ответ 1

Что вам нужно сделать, это:

В базовом классе (где вы объявили события) создайте защищенные методы, которые можно использовать для повышения событий:

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

(Обратите внимание, что вам, вероятно, следует изменить эти методы, чтобы проверить, нужно ли вам вызывать обработчик событий или нет).

Затем в классах, которые наследуются от этого базового класса, вы можете просто вызвать методы OnFinished или OnLoading для повышения событий:

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

Ответ 2

Вы можете получить доступ только к событию в объявляющем классе, так как .NET создает частные переменные экземпляра за кулисами, которые фактически удерживают делегата. Выполнение этого.

public event EventHandler MyPropertyChanged;

на самом деле делает это:

private EventHandler myPropertyChangedDelegate;

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

и делать это...

MyPropertyChanged(this, EventArgs.Empty);

на самом деле это...

myPropertyChangedDelegate(this, EventArgs.Empty);

Таким образом, вы можете (очевидно) получить доступ только к переменной экземпляра частного делегата из класса объявления.

Соглашение должно предоставить что-то подобное в объявляющем классе.

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

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

Затем вы можете вызвать OnMyPropertyChanged(EventArgs.Empty) из любого места этого класса или ниже иерархии наследования для вызова события.

Ответ 3

Я предполагаю, что я не могу получить доступ к этим событиям так же, как другие унаследованные элементы?

Точно. Обычно для защищенной функции OnXyz или RaiseXyz для каждого события в базовом классе допускается повышение из унаследованных классов. Например:

public event EventHandler Loading;

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

Вызывается в унаследованном классе:

OnLoading();

Ответ 4

Вы можете попробовать это, Он работает для меня:

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