2014-02-19 4 views
0

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

http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx

В этом примере экземпляр EventListener подписан на экземпляр ListWithChangedEvent. Используя шаблон наблюдателя ванили, было бы легко получить объекты коллекции, которые слушают ListWithChangedEvent (так как в любом случае он должен поддерживать коллекцию наблюдателей). Однако, используя события, его немного менее понятно, как создать эту коллекцию в ListWithChanged объектов-наблюдателей.

Является ли это что-то вроде:

Changed.GetInvocationList().Select(item => item.Target).OfType<EventListener>().ToList(); 

Кажется сомнительным, это кажется немного сложным.

Редактировать: Это компилируется и дает мне мой ответ. Я просто немного опасаюсь, что это плохой способ сделать это.

+0

Составил ли он? Это сработало? Можете ли вы разбить его? – Gusdor

+0

Вы пытаетесь сделать это * внутри * объекта, который несет ответственность за событие? Что вы пытаетесь достичь с этим? Что бы вы хотели со статическими методами? Вы также должны иметь в виду, что код, выполняющий подписку, может не быть кодом, содержащим метод, который обрабатывает событие ... –

+0

@Gusdor Да. Это было скомпилировано, извините, я думал, что это не так. Тем не менее, я все еще сомневаюсь в этом, но я удивлен тем, что мне очень сложно получить список экземпляров класса прослушивания. –

ответ

1

Вы просто должны помнить, что вы не можете использовать GetInvocationList() для делегатов, помеченных event вне класса объявления, поэтому вам нужно либо объявить фоновое поле, либо сделать звонок от внутри класса.

class EventListener 
{ 
    public EventPublisher publisher = new EventPublisher(); 

    public EventListener() 
    { 
     publisher.Event += HandleEvent; 
    } 

    void HandleEvent(object sender, EventArgs e) 
    { 
    } 
} 

class EventPublisher 
{ 
    public event EventHandler Event; 

    public List<EventListener> GetListeners() 
    { 
     return Event.GetInvocationList().Select(i => i.Target).OfType<EventListener>().ToList(); 
    } 
} 

EDIT: Если вы имеете дело с классом 3-й партии, так что вы не можете использовать поле подкладочный или позвоните GetInvocationList() в классе, то вы можете использовать отражение:

var fieldInfo = typeof(EventPublisher).GetField("Event", BindingFlags.Instance | BindingFlags.NonPublic); 
var eventHandler = (EventHandler)fieldInfo.GetValue(listener.publisher); 
var listeners = eventHandler.GetInvocationList().Select(i => i.Target).ToList(); 
+0

Спасибо. Но знаете ли вы, как явный способ объявления события отличается от стандартной реализации? –

+0

См. Редактирование в моем ответе – Dominic

+0

Вы * можете * получить сам делегат внутри класса, объявляющего полевое событие. (Я просто дважды проверял, чтобы быть уверенным.) Также обратите внимание, что реализация вашего события не является потокобезопасной, в отличие от реализации для полевых событий. –

Смежные вопросы