Подтвердить что ты не робот

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

Мне нужно скопировать подписчиков одного события на другое событие. Могу ли я получить подписчиков события (например, MyEvent [0], возвращающего делегата)?

Если это невозможно, я бы использовал add accessor для добавления делегатов в список. Будет ли это лучшим решением?

4b9b3361

Ответ 1

События/делегаты С# являются многоадресными, поэтому делегат сам по себе является списком. Изнутри класса, чтобы получить отдельных абонентов, вы можете использовать:

if(field != null) { // or the event-name for field-like events
    // or your own event-type in place of EventHandler
    foreach(EventHandler subscriber in field.GetInvocationList())
    {
        // etc
    }
}

Однако, чтобы назначить все сразу, просто используйте + = или прямое назначение:

SomeType other = ...
other.SomeEvent += localEvent;

Ответ 2

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

Если это ваш собственный код, который публикует событие, это легко - вы можете сделать аксессуры добавления/удаления делать все, что вам нравится.

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

Ответ 3

Обновление (спасибо комментаторам): immointability делегата означает, что клонирование ничего не достигает над назначением.

Когда вы пишете:

myDelegate += AHandler

создается новый новый экземпляр делегата и назначается myDelegate.

Следовательно, приведенный ниже код будет работать точно так же без вызова Clone.


MulticastDelegate (базовый тип) имеет метод Clone.

Чтобы получить доступ к базовому делегату, вам может потребоваться избежать обычного помощника, генерируемого ключевым словом события, и управлять вещами напрямую (пользовательский добавить и удалить аксессоры).

Чтобы показать это:

    class Program {
        public delegate void MyDelegate(string name);

        public event MyDelegate EventOne;

        public void HandlerOne(string name) {
            Console.WriteLine("This is handler one: {0}", name);
        }
        public void HandlerTwo(string name) {
            Console.WriteLine("This is handler two: {0}", name);
        }
        public void HandlerThree(string name) {
            Console.WriteLine("This is handler three: {0}", name);
        }

        public void Run() {
            EventOne += HandlerOne;
            EventOne += HandlerTwo;
            Console.WriteLine("Before clone");
            EventOne("EventOne");

            MyDelegate eventTwo = (MyDelegate)EventOne.Clone();
            MyDelegate eventTwo = EventOne;
            Console.WriteLine("After clonecopy");
            EventOne("EventOne");
            eventTwo("eventTwo");

            Console.WriteLine("Change event one to show it is different");
            EventOne += HandlerThree;
            EventOne("EventOne");
            eventTwo("eventTwo");
        }

        static void Main(string[] args) {
            (new Program()).Run();
        }
    }

Ответ 4

Если вам нужно изучить подписчиков события внешнего класса:

EventHandler e = typeof(ExternalClass)
    .GetField(nameof(ExternalClass.Event), BindingFlags.Instance | BindingFlags.NonPublic)
    .GetValue(instanceOfExternalClass) as EventHandler;
if (e != null)
{
    Delegate[] subscribers = e.GetInvocationList();
}