C# 从基类引发事件

C# 从基类引发事件,c#,.net,winforms,events,inheritance,C#,.net,Winforms,Events,Inheritance,我知道可以在实现声明发生的类中引发事件,但我希望在基类级别引发事件并引发派生类的事件: public interface IFoo { event EventHandler<FooEventArgs> FooValueChanged; void RaiseFooValueChanged(IFooView sender, FooEventArgs e); } [TypeDescriptionProvider(typeof(FooBaseImplementor))]

我知道可以在实现声明发生的类中引发事件,但我希望在基类级别引发事件并引发派生类的事件:

public interface IFoo
{
    event EventHandler<FooEventArgs> FooValueChanged;
    void RaiseFooValueChanged(IFooView sender, FooEventArgs  e);
}

[TypeDescriptionProvider(typeof(FooBaseImplementor))]
public abstract class FooBase : Control, IFoo
{
    public virtual event EventHandler<FooEventArgs> FooValueChanged;

    public void RaiseFooValueChanged(IFooView sender, FooEventArgs e)
    {
        FooValueChanged(sender, e);
    }
}
公共接口IFoo
{
事件处理程序FooValueChanged;
void raisefovaluechanged(IFooView sender,FooEventArgs e);
}
[TypeDescriptionProvider(typeof(FooBaseImplementor))]
公共抽象类FooBase:Control,IFoo
{
公共虚拟事件事件处理程序已更改;
public void raisefovaluechanged(IFooView发送方、FooEventArgs e)
{
FooValueChanged(发送方,e);
}
}
我不能让FooValueChanged事件抽象,因为这样基类就不能引发事件。当前代码运行,但调用FooValueChanged(sender,e)会引发NullReferenceException,因为它不调用派生类的事件,而只调用基类的事件

我哪里做错了


我可以将事件和提升器都抽象,但是我需要记住在每个派生类中调用FooValueChanged(sender,e)。在能够使用Visual Studio designer进行派生控件时,我试图避免这种情况。

为什么需要使用事件?你不能只使用重写的方法吗。基类调用可重写方法,该方法被派生类“截获”,然后派生类可以引发事件?

首先,您使用的事件声明是C#中的简写符号:

相当于:

private EventHandler backEndStorage;
public event EventHandler Event {
    add { this.backEndStorage += value; }
    remove { this.backEndStorage -= value; }
}
public void RaiseEvent() {
    this.backEndStorage(this, new EventArgs());
}
其中后端存储是一个多播委托


现在,您可以重写代码:

public interface IFoo
{
    event EventHandler<FooEventArgs> FooValueChanged;
    void RaiseFooValueChanged(IFooView sender, FooEventArgs  e);
}

[TypeDescriptionProvider(typeof(FooBaseImplementor))]
public abstract class FooBase : Control, IFoo
{
    protected event EventHandler<FooEventArgs> backEndStorage;
    public event EventHandler<FooEventArgs> FooValueChanged {
        add { this.backEndStorage += value; }
        remove { this.backEndStorage -= value; }
    }

    public void RaiseFooValueChanged(IFooView sender, FooEventArgs e)
    {
        this.backEndStorage(sender, e);
    }
}

public class FooDerived : FooBase {
    public event EventHandler<FooEventArgs> AnotherFooValueChanged {
        add { this.backEndStorage += value; }
        remove { this.backEndStorage -= value; }
    }
}
公共接口IFoo
{
事件处理程序FooValueChanged;
void raisefovaluechanged(IFooView sender,FooEventArgs e);
}
[TypeDescriptionProvider(typeof(FooBaseImplementor))]
公共抽象类FooBase:Control,IFoo
{
受保护的事件处理程序后端存储;
公共事件事件处理程序已更改{
添加{this.backEndStorage+=value;}
删除{this.backEndStorage-=value;}
}
public void raisefovaluechanged(IFooView发送方、FooEventArgs e)
{
这是后端存储(发送方,e);
}
}
公共类FooDelived:FooBase{
公共事件处理程序另一个FooValueChanged{
添加{this.backEndStorage+=value;}
删除{this.backEndStorage-=value;}
}
}
因此,现在在派生类上添加事件时,它们实际上将添加到基类的后端存储中,从而允许基类调用在派生类中注册的委托。

最终结果:

public interface IFoo
{
    event EventHandler<FooEventArgs> FooValueChanged;
    void RaiseFooValueChanged(IFooView sender, FooEventArgs e);
}

[TypeDescriptionProvider(typeof(FooBaseImplementor))]
public abstract class FooBase : Control, IFoo
{
    protected event EventHandler<FooEventArgs> backEndStorage;
    public abstract event EventHandler<FooEventArgs> FooValueChanged;

    public void RaiseFooValueChanged(IFooView sender, FooEventArgs e)
    {
        if (backEndStorage != null)
            backEndStorage(sender, e);
    }
}

public class FooDerived : FooBase {
    public override event EventHandler<FooEventArgs> FooValueChanged {
        add { backEndStorage += value; }
        remove { backEndStorage -= value; }
    }
}
公共接口IFoo
{
事件处理程序FooValueChanged;
void raisefovaluechanged(IFooView sender,FooEventArgs e);
}
[TypeDescriptionProvider(typeof(FooBaseImplementor))]
公共抽象类FooBase:Control,IFoo
{
受保护的事件处理程序后端存储;
公共抽象事件事件处理程序已更改;
public void raisefovaluechanged(IFooView发送方、FooEventArgs e)
{
if(后端存储!=null)
后端存储(发送方,e);
}
}
公共类FooDelived:FooBase{
公共覆盖事件EventHandler FooValueChanged{
添加{backEndStorage+=value;}
删除{backEndStorage-=value;}
}
}

回答得很好,几乎完全符合我的要求。我将发布我的最终解决方案,使用您的建议。谢谢。请注意,基于您可以做的:
protectedeventhandler backEndStorage=delegate{}
然后不检查null。对于阅读此问题并对我为什么有TypeDescriptionProvider感到困惑的任何人:
public interface IFoo
{
    event EventHandler<FooEventArgs> FooValueChanged;
    void RaiseFooValueChanged(IFooView sender, FooEventArgs e);
}

[TypeDescriptionProvider(typeof(FooBaseImplementor))]
public abstract class FooBase : Control, IFoo
{
    protected event EventHandler<FooEventArgs> backEndStorage;
    public abstract event EventHandler<FooEventArgs> FooValueChanged;

    public void RaiseFooValueChanged(IFooView sender, FooEventArgs e)
    {
        if (backEndStorage != null)
            backEndStorage(sender, e);
    }
}

public class FooDerived : FooBase {
    public override event EventHandler<FooEventArgs> FooValueChanged {
        add { backEndStorage += value; }
        remove { backEndStorage -= value; }
    }
}