Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raising event from base class

I understand that one can raise an event in the class that the implementation declaration occurs, but I wish to raise the event at the base class level and have the derived class's event be raised:

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 FooValueChanged event abstract, because then the base class cannot raise the event. Current the code runs, but the call FooValueChanged(sender, e) throws a NullReferenceException because it doesn't call the derived class's event, only that of the base class.

Where am I going wrong?

I can have the event and the raiser both abstract, but then I need to remember to call FooValueChanged(sender, e) in every single derived class. I'm trying to avoid this while being able to use the Visual Studio designer for derived controls.

like image 485
Llyle Avatar asked Dec 14 '22 05:12

Llyle


1 Answers

Note first, the event declaration that you are using is a short-hand notation in C#:

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

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

Where backEndStorage is a multi-cast 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 when events are added on the derived class, they will actually be added to the backEndStorage of the base class, hence allowing the base class to call the delegates registered in the derived class.

like image 179
earlNameless Avatar answered Dec 30 '22 00:12

earlNameless