Enforcing implementation of events in derived abst

2019-06-19 12:12发布

问题:

I am trying to create what I am thinking of as a translation class, so that my program can speak to a variety of target platforms. Each platform will be handled by a separate implementation of an abstract class. I have pared things down for the sake of simplicity.

I have an abstract class, with a couple of abstract methods:

abstract class ControllerBase
{
    public abstract bool EnableDTMFDetection(string CallID, Party Party);
    public abstract bool DisableDTMFDetection(string CallID, Party Party);
}

Subsequently a class (classes) which derive from ControllerBase, and fully implement those methods:

class PlatformOne : ControllerBase
{
    public override bool EnableDTMFDetection(string CallID, Party Party)
    {
        // Do Stuff
        return true;
    }

    public override bool DisableDTMFDetection(string CallID, Party Party)
    {
        // Do Stuff
        return true;
    }
}

So far so good. For PlatformOne I am forced to define each of those methods, prescribing how I will send an outgoing message to my target platform.

It is the incoming events that have got me. I need to be able to raise events from within my derived classes. When I add the following to controllerbase:

    public delegate void MyEventHandler(object sender, EventArgs e);
    public event MyEventHandler MyEvent;

It compiles fine, but I can't raise the event from within my derived class without the error: "The event 'ControllerBase.MyEvent' can only appear on the left hand side of += or -= (except when used from within the type 'ControllerBase')"

So, a) How do I raise my event from within my derived class, and b) can anyone suggest a mechanism for enforcing the wiring up of specified events from within my derived class (a la abstract functions or interface methods). Thank you call :)

回答1:

The simplest way of doing this is to write a method in your base class to raise it:

protected void OnMyEvent(EventArgs e)
{
    // Note the copy to a local variable, so that we don't risk a
    // NullReferenceException if another thread unsubscribes between the test and
    // the invocation.
    EventHandler handler = MyEvent;
    if (handler != null)
    {
        handler(this, e);
    }
}

You may want to make it a virtual method so you can override it in derived classes... it depends on your use case.

Note that this isn't forcing an implementation of anything in the derived class - but I think it's what you actually want.



回答2:

The standard pattern is to add an On<EventName> virtual protected method to raise an event

protected virtual OnMyEvent(EventArgs e) {
    var h = MyEvent;
    if (h != null)
        h(this, e);
}

Also bear in mind that events can be made abstract or virtual:

public abstract event MyEventHandler MyEvent;

although this is only generally used in interfaces, which might be better for your ControllerBase depending on your exact requirements:

public interface IController {
    event MyEventHandler MyEvent;
    bool EnableDTMFDetection(string CallID, Party Party);
    bool DisableDTMFDetection(string CallID, Party Party);
}

public PlatformOne : IControllerBase

    // yadda yadda...

    public event MyEventHandler MyEvent;

    // members of PlatformOne can invoke MyEvent as a normal delegate
}


回答3:

Create a protected event invocator in the abstract class.

protected void InvokeMyEvent(EventArgs args)
{
    var handler = MyEvent;
    if (hander != null)
        handler(this, args);
}