2009-06-01 12 views
7

La mia classe ha un evento che gli oggetti esterni sottoscriverà:Inoltro/inoltro eventi .NET

public event EventHandler<MessageReceivedEventArgs> MessageReceived; 

Tuttavia, un oggetto Listener interno, in esecuzione su di essa la propria discussione, sarà effettivamente origine dell'evento.

private class Listener 
{ 
    public void Run() 
    { 
     // events raised here which should be forwarded 
     // to parent's MessageReceived 
    } 
}; 

La mia inclinazione è quello di creare un evento con la stessa firma sul Listener, e sottoscrivere nella classe principale, al fine di raccogliere su MessageReceived. Questo mi sembra un po 'macchinoso, quindi mi chiedevo se c'è un modo accurato/idiomatico di inoltrare eventi come questo.

risposta

22

È possibile utilizzare evento add/remove accessors in modo che gli eventi collegati alla manifestazione esterna rivolta vengono "trasmessi" per l'ascoltatore interno

public event EventHandler<MessageReceivedEventArgs> MessageReceived { 
    add { this.listener.MessageRecieved += value; } 
    remove { this.listener.MessageRecieved -= value; } 
} 

Ciò significa che è necessario creare un evento in chi ascolta, ma il vantaggio è che non ci sono altri impianti idraulici per collegare l'evento.

+8

Questa è una soluzione piacevole, ma tenere presente che il gestore di eventi riceverà l'istanza di Listener come argomento del mittente, che potrebbe essere un problema ... –

+0

Bello, mi piace! – marijne

+1

Anche un buon punto sul mittente ... – marijne

1

È possibile farlo con un evento oppure è possibile creare un metodo nella classe principale denominato ReceiveMessage() e chiamarlo dal listener (e quindi generare l'evento da lì).

1

Come è stato risposto, è possibile avere una logica di sottoscrizione personalizzata utilizzando add e remove handlers sul proprio evento.

Si noti che questo design ha un problema così com'è. Si specifica che il listener sta generando l'evento nel proprio thread. Per impostazione predefinita, i gestori verranno chiamati sul thread che ha generato l'evento (nel tuo caso, il thread del Listener). Hai diverse opzioni.

  • Se non si cura che il thread del Listener esegua i callback. Basta chiamare l'evento così com'è (ma il thread del listener può essere bloccato se un gestore di eventi richiede un po 'di tempo per eseguire, o semplicemente morire se un gestore di eventi genera un'eccezione non gestita)
  • Se si desidera che i gestori eseguano in thread diversi da Listener thread, ma non importa in quali thread fintanto che non è nel listener: nel metodo OnXXX che chiama effettivamente i gestori, ottenere l'elenco di invocazioni dell'evento e accodare ogni gestore nel threadpool.
  • Se si desidera che i gestori ad essere chiamati in discussioni specifiche: un po 'complicato, è necessario utilizzare un po' di SynchronizationContext (WindowsSynchronizationContext in WinForms, uno personalizzato in altri casi, ecc)

C'è un post sul blog di Roy Osherove che mostra diversi modi per effettuare le chiamate asincrone: http://weblogs.asp.net/rosherove/pages/DefensiveEventPublishing.aspx (ma non vorrei usare le chiamate asincrone sui delegati e invece fare direttamente affidamento sul ThreadPool per chiamare i delegati).

Problemi correlati