C#:提升继承的事件

时间:2009-04-16 13:58:49

标签: c# events inheritance

我有一个包含以下事件的基类:

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')的左侧

我假设我无法像其他继承的成员那样访问这些事件吗?

5 个答案:

答案 0 :(得分:148)

你需要做的是:

在您的基类(您已声明事件的位置)中,创建可用于引发事件的受保护方法:

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

(请注意,您应该更改这些方法,以便检查是否必须调用eventhandler)。

然后,在从该基类继承的类中,您只需调用OnFinished或OnLoading方法来引发事件:

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

答案 1 :(得分:117)

您只能访问声明类中的事件,因为.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)来调用该事件。

答案 2 :(得分:8)

  

我假设我无法像其他继承的成员那样访问这些事件吗?

正。习惯上为基类中的每个事件提供受保护的函数OnXyzRaiseXyz,以便从继承的类中提升。例如:

public event EventHandler Loading;

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

在继承的类中调用:

OnLoading();

答案 3 :(得分:0)

你可以尝试这种方式,它对我有用:

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

答案 4 :(得分:0)

不复活旧线程,但万一有人在找,我所做的就是

protected EventHandler myPropertyChangedDelegate;

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

这使您可以在派生类中继承该事件,以便可以在无需保留+ =语法的情况下包装方法的情况下调用该事件。我想如果您这样做

,仍然可以使用包装方法来做到这一点
public event EventHandler MyPropertyChanged
{
   add { AddDelegate(value); }
   remove { RemoveDelegate(value); }
}