События не делегатского типа - PullRequest
5 голосов
/ 16 июля 2009

Я реализовал класс, который выглядит следующим образом:

[ImmutableObject(true)]
public interface ICustomEvent
{
    void Invoke(object sender, EventArgs e);

    ICustomEvent Combine(EventHandler handler);
    ICustomEvent Remove(EventHandler handler);

    ICustomEvent Combine(ICustomEvent other);
    ICustomEvent Remove(ICustomEvent other);
}

Этот класс CustomEvent работает во многом как MulticastDelegate. Это может быть вызвано. Это может быть объединено с другим CustomEvent. А CustomEvent можно удалить из другого CustomEvent.

Теперь я хочу объявить класс следующим образом:

class EventProvider
{
    public event CustomEvent MyEvent;

    private void OnMyEvent()
    {
        var myEvent = this.MyEvent;
        if (myEvent != null) myEvent.Invoke(this, EventArgs.Empty);
    }
}

К сожалению, этот код не компилируется. Появляется ошибка компилятора CS0066:

'EventProvider.MyEvent': событие должно иметь тип делегата

По сути, мне нужно свойство, которое имеет добавить и удалить методы доступа вместо get и set . Я думаю, что единственный способ добиться этого - использовать ключевое слово event . Я знаю, что одной очевидной альтернативой является объявление двух методов, которые будут добавлять и удалять, но я также хочу этого избежать.

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

Кстати, кто-то задавал похожий вопрос на сайте expert-exchange.com. Поскольку этот сайт не бесплатный, я не вижу ответов. Вот тема: http://www.experts -exchange.com / Программирование / Языки / C_Sharp / Q_21697455.html

Ответы [ 4 ]

5 голосов
/ 16 июля 2009

Попробуйте это:

CustomEvent myEvent

public event EventHandler MyEvent {
    add { myEvent = myEvent.Combine(value); }
    remove {myEvent = myEvent.Remove(value); }
}

Вы можете добавлять и удалять обычные делегаты EventHandler, и он будет выполнять методы доступа add и remove.


EDIT : вы можете найти слабую реализацию события здесь .
2 и РЕДАКТИРОВАТЬ : или здесь .

2 голосов
/ 16 июля 2009

Если вы хотите иметь возможность добавлять и удалять CustomEvent объекты из события (вместо обычных делегатов), есть две опции:

Выполните неявное приведение из ICustomEvent к EventHandler (или другому делегату), который возвращает метод экземпляра ICustomEvent (возможно, Invoke), затем используйте свойство Target делегата, чтобы получить исходный ICustomEvent в add и * 1005. * аксессоры.

РЕДАКТИРОВАТЬ : Как это:

CustomEvent myEvent;
public event EventHandler MyEvent {
    add {
        if (value == null) throw new ArgumentNullException("value");
        var customHandler = value.Target as ICustomEvent;

        if (customHandler != null)
            myEvent = myEvent.Combine(customHandler);
        else
            myEvent = myEvent.Combine(value);   //An ordinary delegate
    }
    remove {
        //Similar code
    }
}

Обратите внимание, что вам все еще нужно выяснить, как добавить первый обработчик, если он является делегатом (если поле myEvent равно null)


Создайте доступное для записи свойство типа CustomEvent, затем перегрузите операторы + и -, чтобы разрешить += и -= для свойства.

РЕДАКТИРОВАТЬ : Чтобы предотвратить перезапись события вызывающими пользователями, вы можете выставить предыдущее значение в CustomEvent (я предполагаю, что оно работает как неизменный стек ) и в сеттер, добавь

if (myEvent.Previous != value && value.Previous != myEvent)
    throw new ArgumentException("You cannot reset a CustomEvent", "value");

Обратите внимание, что при удалении последнего обработчика значения value и myEvent.Previous будут null.

1 голос
/ 16 июля 2009

Чего вы пытаетесь достичь, для чего вы не можете использовать делегатов / события?

Это крики Повторное изобретение квадратного колеса (внизу страницы) , но это может быть и я, не понимая проблему.

0 голосов
/ 17 июля 2009

Почему бы вам не попробовать использовать операторы "+ =" и "- =" в вашем классе CustomEvent? Вы не можете переопределить операторы «+ =» и «- =» напрямую, но они оцениваются операторами «+» и «-».

Операторы присваивания не могут быть перегружены, но + =, например, оценивается с помощью +, который может быть перегружен.

http://msdn.microsoft.com/en-us/library/8edha89s(VS.90).aspx

Таким образом, вместо использования методов добавления и удаления, похожих на события, вы можете иметь поле или свойство, которые могут быть объединены операторами + = и - =. Кроме того, он инкапсулирует комбинационную логику в вашем собственном классе CustomEvent.

Карлос Лот.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...