C#: Raising an Inherited Event

C#: Raising an inherited event

What you have to do , is this:

In your base class (where you have declared the events), create protected methods which can be used to raise the events:

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

(Note that you should probably change those methods, in order to check whether you have to Invoke the eventhandler or not).

Then, in classes that inherit from this base class, you can just call the OnFinished or OnLoading methods to raise the events:

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

C# How to use event in the inherited class

Add the following method to your BaseElement class:

internal void LogInvoke(string report)
{
Log?.Invoke(report);
}

Then you can invoke it from the inherited Button class by calling the LogInvoke method.

public class Button : BaseElement
{
//....

internal void Clear()
{
WebElement.Clear();
LogInvoke("clear");
}
}

Raise event handler in derived class

I found a new solution for this. Simple solution is to make field to Property...

using System;

class Base
{
public event EventHandler OperationsChanged {get; set;}
}
class Derived : Base
{
public void OnSpecificOperationChanged()
{
OperationsChanged(this, EventArgs.Empty);
}
}

class Test
{
static void Main()
{
Derived d = new Derived();
d.OperationsChanged += OnOperationsChanged;

//invoke
d.OnSpecificOperationChanged();

}
static void OnOperationsChanged(object sender, EventArgs e)
{
Console.WriteLine("called");
}
}

Event handler inheritance

I might be wrong but have you thought about making the event static?

public delegate void BufferReadyHandler(string str);
public static event BufferReadyHandler OnBufferReady;

Child/Parent event raising

You can attach to the event from the child instance.

public abstract class Parent
{
public event Action Something;

public void OnSomething()
{
if (Something != null)
{
Something();
}
}
}
public class Child : Parent
{

}

Child c = new Child();
c.Something += () => Console.WriteLine("Got event from child");
c.OnSomething();
> Got event from child

You can even declare it as a Parent type that contains a child:

Parent c2 = new Child();
c2.Something += () => Console.WriteLine("Got event from Parent type");
c2.OnSomething();
> Got event from Parent type

An abstract class is just a code template that gets copied into every class that inherits from it (to put it simply). Think of it like, all of your Child classes contain an identical copy of the code that exists in Parent.


Note that this will also produce a unique event handler for each instance of Child. Having a static event handler for all Childs that derive from Parent would look like this, and requires no code in Child:

public abstract class Parent
{
public static event Action Something;

public static void OnSomething()
{
if (Something != null)
{
Something();
}
}
}

Then, you could do something like this, for example:

Parent.Something += () => Console.WriteLine("This will be invoked twice.");

Child c = new Child();
Child c2 = new Child();
c.OnSomething();
c2.OnSomething();

> This will be invoked twice.
> This will be invoked twice.

Both of those objects/event calls will invoke the same event handler even though they come from separate children.

Inheriting Event Handlers in C#

Declare the parent method virtual, override it in the child classes and call

base.checkReadyness(sender, e);

(or derevation thereof) from within the child class. This allows for future design evolution say if you want to do some specific error checking code before calling the parent event handler. You might not need to write millions of event handlers like this for each control, you could just write one, hook all the controls to this event handler which in turn calls the parent's event handler.

One thing that I have noted is that if all this code is being placed within a dll, then you might experience a performance hit trying to call an event handler from within a dll.

Call an event from a base class

That isn't allowed indeed. If I may recommend an alternative approach:

public abstract class SomeBaseClass
{
public event EventHandler SomeEvent;

protected void RaiseSomeEvent(EventArgs e)
{
var eh = SomeEvent;
if (eh != null)
eh(this, e);
}
}

public class SomeClass : SomeBaseClass
{
public void DoSomething()
{
//TODO
RaiseSomeEvent(EventArgs.Empty);
}
}

Note that I have moved the invocation of the event handler to the owning class, this is required by .NET / C# since only that class can invoke the event handler. Second, I have made the event handler thread safe by assigning it to eh first.

Never hide the base class' event by using the new keyword! You will get unexpected results when you use the base class' type as type for a variable or when the base class invokes the event.

Raise Base Class Events in Derived Classes C#

You cannot directly fire base class events. This is exactly the reason why you had to make your OnShapeChanged method protected instead of private.

Use base.OnMove() instead.

Raising event from base class

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.



Related Topics



Leave a reply



Submit