sembra come dovrei avere tutto ciò di cui ho bisogno qui, ma i dettagli di farlo accadere mi stanno facendo impazzire.Come si può usare un lambda per creare un nuovo EventHandler?
Ho un metodo di utilità statico che accetta un oggetto client di servizio Web, estrae un EventInfo designato da esso e dovrebbe aggiungere alcuni gestori a quell'evento, essenzialmente i callback per il completamento del richiamo del servizio web. Il problema è che, dato che ogni dato evento ha essenzialmente un proprio sovraccarico di gestore (il codice generato da WCF fornisce un SomeMethodCompletedEventArgs
unico per ogni metodo e evento corrispondente), non riesco a capire come farlo accadere.
Ho due gestori che voglio attaccare, e la prima è solo una funzione lambda:
(obj, args) => task.Complete()
Quindi quello che vorrei fare è proprio questo semplice:
eventInfo.AddEventHandler(client, new EventHandler((obj, args) => task.Complete()));
Ciò, tuttavia, genera un InvalidCastException di runtime, poiché eventInfo si aspetta un EventHandler<SomeMethodCompletedEventArgs>
, non un semplice EventHandler
. Credo che ciò significhi che ho bisogno di creare dinamicamente il delegato EventHandler
usando lo eventInfo.EventHandlerType
in qualche modo, ma non ho capito di combinarlo con la funzione lambda, o altrimenti fare un ricevitore che davvero non lo fa care quale particolare sapore di EventArgs
viene Usato.
L'unica soluzione alternativa che ho trovato è creare un argomento modello generico con cui passare il tipo di argomento evento specifico. Questo mi permette di andare:
eventInfo.AddEventHandler(client, new EventHandler<E>(...));
Dove E
è il parametro in questione. Questo è ovviamente clunky, e sembra proprio sbagliato dover passare questo quando l'estratto eventInfo
dovrebbe dirci tutto ciò che dobbiamo sapere.
Vale la pena notare che sto utilizzando un PCL Framework leggermente vincolato per Xamarin, che a quanto pare non include il metodo statico Delegate.CreateDelegate()
che ho visto menzionato in problemi correlati. I do hanno accesso a Activator
, tuttavia, che dovrebbe coprire la maggior parte delle stesse basi.
Si noti che è generalmente sconsigliato per fissare lambda a gestori di eventi, poiché possono essere rimossi solo da un processo di riflessione piuttosto complicato. –
@ObliviousSage: _ "possono essere rimossi solo da un processo di riflessione piuttosto complicato" _ - non è corretto. Innanzitutto, in molti casi non è mai necessario rimuovere il gestore eventi. In secondo luogo, negli scenari in cui è necessario, tutto ciò che è necessario è conservare il riferimento dell'istanza delegata in una variabile da qualche parte e utilizzare tale valore per annullare l'iscrizione al gestore. Non è necessaria alcuna riflessione e in molti casi questa variabile può essere semplicemente una variabile locale catturata. –
@PeterDuniho Sì, i gestori di eventi spesso non devono essere rimossi; non è come dire che dovresti assumere che non sarà necessario rimuoverlo. Sei corretto che un delegato possa essere rimosso se hai salvato un riferimento ad esso, ma un lambda puro (ad esempio, 'myObject.SomeEvent + = (a, b) => Foo();') non può essere rimosso senza la riflessione precedentemente citata. Che gli svantaggi dell'uso di una lambda come gestore di eventi possa essere attenuato non significa che tali svantaggi non esistano, né significa che l'utilizzo di lambda come gestori di eventi sia una buona abitudine per entrare. –