我理解可以在类中引发一个实现声明发生的事件,但我希望在基类级别引发事件并引发派生类的事件:
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);
}
}
我不能拥有FooValueChanged事件摘要,因为基类不能引发事件。当前代码运行,但调用FooValueChanged(sender,e)抛出NullReferenceException,因为它不调用派生类的事件,只调用基类的事件。
我哪里错了?
我可以将事件和提升者都抽象,但是我需要记住在每个派生类中调用FooValueChanged(sender,e)。我试图避免这种情况,同时能够使用Visual Studio设计器进行派生控件。
答案 0 :(得分:10)
首先请注意,您使用的事件声明是C#中的简写符号:
public event EventHandler Event;
public void RaiseEvent() {
this.Event(this, new EventArgs());
}
相当于:
private EventHandler backEndStorage;
public event EventHandler Event {
add { this.backEndStorage += value; }
remove { this.backEndStorage -= value; }
}
public void RaiseEvent() {
this.backEndStorage(this, new EventArgs());
}
backEndStorage是一个多播委托。
现在您可以重写代码:
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; }
}
}
所以现在当在派生类上添加事件时,它们实际上会被添加到基类的backEndStorage中,因此允许基类调用在派生类中注册的委托。
答案 1 :(得分:2)
最终结果:
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; }
}
}
答案 2 :(得分:1)
为什么需要使用活动?你不能只使用重写方法。基类调用可覆盖的方法,该方法由派生类“拦截”,然后可以引发事件?