Обеспечение реализации событий в производных абстрактных классах - PullRequest
6 голосов
/ 04 октября 2010

Я пытаюсь создать то, о чем я думаю, как о классе перевода, чтобы моя программа могла общаться с различными целевыми платформами.Каждая платформа будет обрабатываться отдельной реализацией абстрактного класса.Ради простоты я сократил.

У меня есть абстрактный класс с парой абстрактных методов:

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

Впоследствии класс (классы), производный от ControllerBase,и полностью реализовать эти методы:

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

Пока все хорошо.Для PlatformOne я вынужден определить каждый из этих методов, прописав, как я буду отправлять исходящее сообщение на свою целевую платформу.

Меня получают входящие события.Мне нужно иметь возможность вызывать события из моих производных классов.Когда я добавляю следующее в controllerbase:

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

Он компилируется нормально, но я не могу вызвать событие из моего производного класса без ошибки: «Событие 'ControllerBase.MyEvent' может появляться только влевая часть + = или - = (за исключением случаев, когда используется внутри типа 'ControllerBase') "

Итак, а) Как я могу поднять свое событие из моего производного класса, и б) может ли кто-нибудьпредложить механизм для принудительного связывания указанных событий из моего производного класса (а-ля абстрактные функции или методы интерфейса).Спасибо, звоните :) 1016 *

Ответы [ 3 ]

10 голосов
/ 04 октября 2010

Самый простой способ сделать это - написать метод в базовом классе для его поднятия:

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

Вы можете захотеть сделать его виртуальным методом, чтобы вы могли переопределитьэто в производных классах ... это зависит от вашего варианта использования.

Обратите внимание, что это не форсирование реализации чего-либо в производном классе - но я думаю, что это то, что вы на самом деле хотите.

3 голосов
/ 04 октября 2010

Стандартный шаблон заключается в добавлении On<EventName> виртуального защищенного метода для вызова события

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

Также имейте в виду, что события могут быть абстрактными или виртуальными:

public abstract event MyEventHandler MyEvent;

хотя это обычно используется только в интерфейсах, что может быть лучше для вашего ControllerBase в зависимости от ваших точных требований:

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
}
1 голос
/ 04 октября 2010

Создайте защищенный вызов события в абстрактном классе.

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