Domanda

È noto che è necessario dichiarare gli eventi che assumono come parametri (mittente oggetto, EventArgs args) . Perché?

È stato utile?

Soluzione

Ciò consente allo sviluppatore che consuma la possibilità di scrivere un singolo gestore eventi per più eventi, indipendentemente dal mittente o dall'evento.

Modifica: Perché avresti bisogno di un modello diverso? È possibile ereditare EventArgs per fornire qualsiasi quantità di dati e la modifica del modello servirà solo a confondere e frustrare qualsiasi sviluppatore che è costretto a consumare questo nuovo modello.

Altri suggerimenti

In realtà questo è discutibile se questo è il modo migliore di fare eventi. C'è la scuola di pensiero che, poiché gli eventi hanno lo scopo di disaccoppiare due segmenti di codice, il fatto che il gestore di eventi ottenga il mittente e deve sapere in quale tipo eseguire il cast del mittente per fare qualcosa con esso è un anti- modello.

Perché è un buon modello per qualsiasi meccanismo di callback, indipendentemente dalla lingua. Vuoi sapere chi ha inviato l'evento (il mittente) e i dati pertinenti all'evento (EventArgs).

L'utilizzo di un singolo parametro, EventArgs, per i dati trasmessi da un evento consente di aggiungere dati all'evento nelle versioni future del software senza interrompere i consumatori esistenti. È sufficiente aggiungere nuovi membri a una classe derivata da EventArgs esistente o creare una classe derivata con i nuovi membri.

In caso contrario, la coerenza e il principio della minima sorpresa giustificano l'utilizzo di EventArgs per il passaggio di dati.

Per quanto riguarda il mittente, in alcuni (ma non in tutti) casi è utile sapere quale tipo ha inviato l'evento. L'uso di un tipo diverso dall'oggetto per l'argomento mittente è troppo restrittivo: significherebbe che altri mittenti non potrebbero riutilizzare la stessa firma dell'evento.

È un buon modello da usare, in questo modo ciò che implementa l'evento può trovare ciò che lo stava inviando.

Anche l'override di EventArgs e il passaggio dei dati attraverso di essi è il metodo migliore. Gli EventArgs sono una classe base. Se guardi vari controlli che chiamano eventi, hanno sovrascritto EventArgs che ti dà maggiori informazioni sull'evento.

Anche se non hai bisogno degli argomenti per fare l'evento, se non li includi nella prima esecuzione del framework e vuoi aggiungerli in un secondo momento, interrompi tutte le implementazioni precedenti e devi riscriverle . Inoltre, se stai creando un framework e stai andando a distribuire che diventa peggio perché tutti coloro che usano il tuo framework dovranno rifattorizzare.

Chris Anderson afferma nel libro delle linee guida per la progettazione del framework:

  

[T] il suo è solo uno schema. Avendo pacchetti di eventi in una classe si ottiene una migliore semantica di versioning. Avendo un modello comune (mittente, e) può essere facilmente appreso come firma per tutti gli eventi.

Ci sono situazioni che coinvolgono principalmente l'interoperabilità che richiederebbero deviazioni da questo schema.

Sembrava che questo fosse il modo di Microsoft di evolvere il modello di eventi nel tempo. Sembra anche che stiano anche permettendo un altro modo di farlo con il "nuovo" Delegato d'azione e sue variazioni.

" Mittente oggetto " consente di riutilizzare un metodo per più oggetti quando si suppone che il metodo del gestore faccia qualcosa con l'oggetto che ha generato l'evento, ad esempio la casella di testo 3 può avere un solo gestore che reimposterà il testo della casella di testo di attivazione.

Il vantaggio principale di EventArgs è che consente di refactificare le informazioni sugli eventi senza la necessità di modificare le firme di tutti i gestori in tutti i progetti che sono iscritti a questo tipo di evento.

Non riesco a pensare a un modo più intelligente di gestire gli eventi.

A volte vorresti forzare tutti i tuoi consumatori di eventi a utilizzare un determinato parametro di evento, ad esempio un evento di sicurezza che passa un parametro booleano, vero per bene, falso per cattivo. In questo caso, desideri che i tuoi consumatori siano dolorosamente consapevoli del nuovo parametro, ovvero desideri che i tuoi consumatori siano associati a quel parametro. Prendi nota, i tuoi consumatori sono ancora disaccoppiati dalla tua classe di fuoco dell'evento, ma non dal tuo evento.

Sospetto che questo scenario si applichi a un gran numero di casi e in questi casi il valore di EventArgs è notevolmente ridotto.

La sola classe EventArgs è inutile poiché deve essere derivata per creare un'istanza con qualsiasi contenuto. Ciò indicherebbe che dovrebbe essere utilizzata una sottoclasse, e molti già esistono in .NET. Purtroppo, non riesco a trovare quelli buoni generici.

Supponiamo che tu voglia delegare la registrazione a un evento generico ... SENZA SCRIVERE IL PROPRIO SUBCLASS EventArgs. Può sembrare un esercizio inutile, ma mi piace usare le funzionalità esistenti. Puoi passare la tua stringa attraverso l'argomento Object, ma ciò va contro l'uso previsto. Prova a trovare un buon riferimento alle sottoclassi di EventArgs su Google e verrai asciutto. (Almeno l'ho fatto.)

ReSharper aiuta un po ', poiché quando digiti " EventArgs " vedrai un elenco di tutte le classi (nell'ambito del tuo utilizzo / importazione) CHE CONTENGONO la stringa "EventArgs". Esaminando l'elenco vedrai molte classi senza membri della stringa. Quando arrivi a ControlEventArgs , vedi che potrebbe essere utilizzata la proprietà Text, ma con tutto il sovraccarico di un controllo di Windows. ConvertEventArgs potrebbe essere utile, dal momento che si passa il tipo insieme ai dati, ma ciò richiede comunque un accoppiamento stretto che non è né ben documentato né intrinsecamente sicuro. DataReceivedEventArgs non ha implementazione. EntryWrittenEventArgs richiede un EventLogEntry con una matrice di byte o StreamingContext per i dati. ErrorEventArgs è più vicino, con un messaggio di eccezione, se non ti dispiace chiamare tutti i tuoi eventi di registro Error ErrorEvents internamente. FileSystemEventArgs è probabilmente il più vicino, con due stringhe e un argomento ener WatcherChangeTypes obbligatorio che PUO 'essere impostato su 0, se sai cosa stai facendo. LabelEditEventArgs utilizza un int e una stringa, se non ti dispiace richiedere lo spazio dei nomi Windows.Forms. RenamedEventArgs è simile a FileSystemEventArgs con una stringa aggiuntiva. Infine, ResolveEventArgs in System.Runtime.InteropServices passa una singola stringa. Ci sono altre biblioteche, ma mi sono attenuto ad alcune delle più comuni. Quindi, a seconda dell'implementazione, posso usare ErrorEventArgs , FileSystemEventArgs o ResolveEventArgs per la registrazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top