Raising an event from a base class

I understand that it is possible to create an event in a class that has an implementation declaration, but I want to raise this event at the base class level and create a derived class event:

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

I cannot have the abstract event of the FooValueChanged event, because then the base class cannot raise the event. The current code is launched, but calling FooValueChanged (sender, e) throws a NullReferenceException because it does not raise an event of the derived class, but only the base class class.

Where am I going wrong?

I can have an event, and raiser is abstract, but then I need to remember the call to FooValueChanged (sender, e) in each derived class. I try to avoid this by being able to use the Visual Studio constructor for derived controls.

+4
source share
3 answers

Please note that the ad declaration you use is a short notation in C #:

 public event EventHandler Event; public void RaiseEvent() { this.Event(this, new EventArgs()); } 

It is equivalent to:

 private EventHandler backEndStorage; public event EventHandler Event { add { this.backEndStorage += value; } remove { this.backEndStorage -= value; } } public void RaiseEvent() { this.backEndStorage(this, new EventArgs()); } 

If backEndStorage is a multi-sheet delegate.


Now you can rewrite your code:

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

So now that events are added to the derived class, they will actually be added to the backEndStorage of the base class, therefore, allowing the base class to call delegates registered in the derived class.

+10
source

Final result:

 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
source

Why do you need to use the event? Can't you use an overridden method. Does the base invoke an overridable method that is "caught" by the derived class, which can then raise the event?

+1
source

All Articles