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


Можно ли при отладке заглянуть в textBox1.TextChanged, чтобы узнать количество подписок на события? Если да,то как мне к нему подойти? Мне нужно знать, сколько подписок существует в данный момент времени для отладки, потому что это выглядит так, как будто событие запускается несколько раз, но я подозреваю, что эта ошибка на самом деле потому, что textBox1.TextChanged += handler неправильно управляется в приложении, поэтому слишком много подписчиков.

Вот упрощенная версия того, что, по моему мнению, происходит. Если возможно, я просто хочу установить остановитесь и подсчитайте количество подписок на " textBox1.TextChanged":
private void textBox1_TextChanged(object sender, EventArgs e)
{
    textBox1.TextChanged += textBox1_TextChanged;
    MessageBox.Show("asdf");
    textBox1.TextChanged -= textBox1_TextChanged;        
    textBox1.Text = DateTime.Now.ToString();
    textBox1.TextChanged += textBox1_TextChanged;
}

Возможно ли это или это более сложно?

4 5

4 ответа:

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

    textBox1.TextChanged += textBox1_TextChanged;
    MessageBox.Show("asdf");
    textBox1.TextChanged -= textBox1_TextChanged;        
    textBox1.Text = DateTime.Now.ToString();
    textBox1.TextChanged += textBox1_TextChanged;
    var eventField = textBox1.GetType().GetField("TextChanged", BindingFlags.GetField
                                                               | BindingFlags.NonPublic
                                                               | BindingFlags.Instance);

    var subscriberCount = ((EventHandler)eventField.GetValue(textBox1))
                .GetInvocationList().Length;

Если вы заинтересованы только в том, чтобы сделать это под отладчиком, а не программно, то это, возможно, более простой, неинвазивный способ:

class _24003458
{
    event EventHandler MyEvent;
    public void Test()
    {
        MyEvent += Handler1;
        MyEvent += Handler2;
        MyEvent(this, EventArgs.Empty);
    }
    void Handler1(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
    void Handler2(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
}

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

Скриншот программы остановленной в точке останова и локальное окно, показывающее развернутое событие с количеством вызовов и обработчиками

это невозможно с таким событием (по уважительной причине), однако, это достижимо через отражение, как Selman22 говорит, выше ) Если вы используете событие непосредственно, вы можете сделать так:

private event EventHandler handler;

var delegates = handler.GetInvocationList();

Можно создать метод-член, который добавляется к объекту, реализующему интерфейс INotifyPropertyChanged. Это делает отладку очень простой:

#if DEBUG
    public System.Delegate[] GetInvocationList()
    {
        return PropertyChanged?.GetInvocationList();
    }
#endif