Patrick Skelton Ответов: 2

Как получить количество подписчиков событий в блоках добавления и удаления?


Если я использую явный синтаксис для объявления события, можно ли получить количество подписчиков внутри то add {} и remove {} кодовые блоки? Например:

public event EventHandler MyEvent
{
    add
    {
        MyEvent += value;
        // Can I get a count of subscribers here?
    }
    remove
    {
        MyEvent -= value;
        // And also here?
    }
}


Что я уже пробовал:

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

MyEvent.GetInvocationList().Count


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

Richard MacCutchan

Что происходит, когда вы пытаетесь это сделать?

Patrick Skelton

Он не будет компилироваться. Он говорит что-то вроде " MyEvent может появиться только с левой стороны += или -=".

Bernhard Hiller

А как насчет этого?GetInvocationList ()?

Patrick Skelton

Ключевое слово "this", по-видимому, относится к заключающему классу, поэтому я получаю сообщение о том, что класс не содержит метода GetInvocationList().

Я предполагаю, что, возможно, это невозможно, потому что то, что я пытаюсь сделать, - это получить ссылку на экземпляр класса, который компилятор C# генерирует автоматически в ответ на ключевое слово "событие".

Tomas Takac

Почему? Каков ваш вариант использования? Я не думаю, что вы можете сделать это изнутри Add/remove accessors. Если у вас есть пользовательские методы доступа, вы можете иметь счетчик, который вы увеличиваете или уменьшаете при добавлении/удалении. Или вы можете отбросить пользовательские методы доступа и получить счетчик с помощью GetInvocationList() в любом месте вашего класса. Все зависит от того, чего вы пытаетесь достичь.

Patrick Skelton

Я просто пытаюсь зарегистрировать количество в отладочной сборке, чтобы следить за потенциальными утечками памяти. Я буду использовать отдельную переменную count, как вы предлагаете. Тем не менее, кажется постыдным вводить переменную и связанный с ней код, который будет существовать только в отладочной сборке и поэтому должен быть завернут в #if DEBUG ... #за endif.

Спасибо всем.

Tomas Takac

Посмотрите на решение №2. Думаю, это решит вашу проблему.

2 Ответов

Рейтинг:
4

OriginalGriff

Вы можете сделать это только из класса, который создает событие:

public class MyClass
    {
    public event EventHandler MyEvent;
    protected virtual void OnMyEvent(EventArgs e)
        {
        EventHandler eh = MyEvent;
        if (eh != null)
            {
            eh(this, e);
            }
        }
    public int CountEvents()
        {
        return MyEvent.GetInvocationList().Length;
        }
    }
...
private void MyButton_Click(object sender, EventArgs e)
    {
    MyClass mc = new MyClass();
    mc.MyEvent += mc_MyEvent;
    Console.WriteLine(mc.CountEvents());
    mc.MyEvent += mc_MyEvent;
    Console.WriteLine(mc.CountEvents());


Patrick Skelton

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

Спасибо.

Рейтинг:
12

Peter Vegter

Как насчет этого?

private EventHandler _myEvent;
private int _myEventSubscribersCount;

public event EventHandler MyEvent
{
    add
    {
        _myEvent += value;
        _myEventSubscribersCount = _myEvent.GetInvocationList().Length;
    }

    remove
    {
        _myEvent -= value;
        _myEventSubscribersCount = _myEvent.GetInvocationList().Length;
    }
}


Patrick Skelton

Отлично. На самом деле, поскольку все, что я делаю,-это немного отладочного протоколирования внутри "добавить" и "удалить", мне даже не нужна переменная count. Что хорошо, потому что это означает, что мне не нужна ни одна отладка #if, и мой окончательный код выпуска почти такой же, как если бы я использовал более простой синтаксис объявления событий типа свойств.

Большое спасибо.

Peter Vegter

Пожалуйста. Спасибо за ответ.
Хорошая "проблема", мне нужна была эта конструкция, чтобы запустить и остановить опцию, управляемую таймером...
Счастливого кодирования, Питер