Как я могу получить все методы события? - PullRequest
1 голос
/ 23 сентября 2010

У меня есть событие Load

public delegate void OnLoad(int i);
public event OnLoad Load;

Я подписываюсь на него методом:

public void Go()
{
    Load += (x) => { };
}

Возможно ли получить этот метод с помощью отражения?Как?

Ответы [ 3 ]

8 голосов
/ 23 сентября 2010

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

A похожее на поле событие , как вы только что показали, просто поддерживается полем соответствующего типа делегата с автоматически сгенерированными обработчиками добавления / удаления, которые просто используют это поле. Однако нечего сказать, что у них есть для такой реализации. Например, событие может хранить своих подписчиков в EventHandlerList, что эффективно, если у вас есть несколько событий в классе, и только некоторые из них, вероятно, будут подписаны.

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

РЕДАКТИРОВАТЬ: Я предполагаю, что вы говорите о получении подписчиков из за пределами класса, объявляющего событие. Если вы внутри класса, объявляющего событие, то это легко, потому что вы знаете, как хранится событие.

В этот момент проблема переходит от «извлечения подписчиков события» к «извлечению отдельных делегатов, составляющих многоадресный делегат» - и это легко. Как уже говорили другие, вы можете вызвать Delegate.GetInvocationList, чтобы получить массив делегатов ... и затем использовать свойство Delegate.Method, чтобы получить метод, на который нацелен данный конкретный делегат.

Теперь давайте еще раз посмотрим на код вашей подписки:

public void Go()
{
    Load += (x) => { };
}

Метод, который используется здесь для создания делегата, не Go ... это метод, созданный компилятором C #. У него будет «неописуемое имя» (обычно с угловыми скобками), поэтому оно будет выглядеть примерно так:

[CompilerGenerated]
private static void <Go>b__0(int x)
{
}

Теперь, это на самом деле то, что вы хотите получить? Или вы действительно хотели узнать, какой метод выполнял подписку, а не какой метод использовался в качестве обработчика подписки ?

0 голосов
/ 23 сентября 2010

Вы можете использовать метод GetInvocationList , который даст вам всех подписчиков.

0 голосов
/ 23 сентября 2010

Если вы вызываете Load.GetInvocationList (), вам будет возвращен массив типов делегатов.Из этих типов вы можете получить доступ к MethodInfo.

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