Domanda Casi d'uso per la riflessione


Recentemente stavo parlando con un collaboratore di C ++ e mi sono lamentato che non c'era modo di prendere una stringa con il nome di un campo di classe ed estrarre il campo con quel nome; in altre parole, manca di riflessione. Mi ha rivolto uno sguardo sconcertato e ha chiesto quando qualcuno avrebbe mai avuto bisogno di fare una cosa del genere.

In cima alla mia testa non avevo una buona risposta per lui, a parte "hey, ho bisogno di farlo subito". Così mi sono seduto e ho trovato un elenco di alcune delle cose che ho fatto con la riflessione in varie lingue. Sfortunatamente, molti dei miei esempi provengono dalla mia programmazione web in Python, e speravo che la gente qui avrebbe avuto più esempi. Ecco la lista che ho trovato:

  1. Dato un file di configurazione con linee come
    x = "Ciao mondo!"
    y = 5,0
    imposta dinamicamente i campi di alcuni config oggetto uguale ai valori in quel file. (Questo era quello che avrei voluto fare in C ++, ma in realtà non potevo farlo.)

  2. Quando si ordina un elenco di oggetti, ordina in base a un attributo arbitrario dato il nome di tale attributo da un file di configurazione o da una richiesta web.

  3. Quando si scrive un software che utilizza un protocollo di rete, reflection consente di chiamare metodi basati su valori stringa da quel protocollo. Ad esempio, ho scritto un bot IRC che avrebbe tradotto
    !some_command arg1 arg2
    in una chiamata di metodo actions.some_command(arg1, arg2) e stampare qualsiasi funzione restituita al canale IRC.

  4. Quando si utilizza la funzione __getattr__ di Python (che è un po 'come method_missing in Ruby / Smalltalk) stavo lavorando con una classe con un sacco di statistiche, come late_total. Per ogni statistica, volevo essere in grado di aggiungere _percent per ottenere quella statistica come percentuale delle cose totali che stavo contando (ad esempio, stats.late_total_percent). La riflessione lo ha reso molto facile.

Quindi chiunque può dare qualche esempio dalle proprie esperienze di programmazione di momenti in cui la riflessione è stata utile? La prossima volta che un collega mi chiede perché mai "voglio fare qualcosa del genere" mi piacerebbe essere più preparato.


17
2017-09-08 13:46


origine


risposte:


Posso elencare il seguente utilizzo per la riflessione:

  • Rilegatura tardiva
  • Sicurezza (codice introspettivo per motivi di sicurezza)
  • Analisi del codice
  • Digitazione dinamica (la digitazione anatra non è possibile senza riflessione)
  • metaprogrammazione

Alcuni usi reali della riflessione dalla mia esperienza personale:

  • Sistema di plugin sviluppato basato sulla riflessione
  • Utilizzato modello di programmazione orientato all'aspetto
  • Eseguita analisi del codice statico
  • Utilizzati vari framework di Iniezione delle dipendenze
  • ...

La riflessione è buona cosa :)


14
2017-09-08 14:08



Ho usato il reflection per ottenere informazioni sul metodo corrente per eccezioni, registrazione, ecc.

string src = MethodInfo.GetCurrentMethod().ToString();
string msg = "Big Mistake";
Exception newEx = new Exception(msg, ex);
newEx.Source = src;

invece di

string src = "MyMethod";
string msg = "Big MistakeA";
Exception newEx = new Exception(msg, ex);
newEx.Source = src;

È solo più facile per l'ereditarietà di copia / incolla e la generazione del codice.


4
2017-09-08 14:01



Mi trovo in una situazione in cui ho un flusso di XML in arrivo sul filo e ho bisogno di istanziare un oggetto Entity che si popolerà da elementi nel flusso. È più semplice usare la riflessione per capire quale oggetto Entity può gestire quale elemento XML piuttosto che scrivere un'enunciazione condizionale gigantesca, che richiede manutenzione e incubo. Esiste chiaramente una dipendenza tra lo schema XML e il modo in cui strutturo e denominano i miei oggetti, ma controllo entrambi, quindi non è un grosso problema.


3
2017-09-08 14:06



Ci sono molte volte in cui si desidera creare un'istanza e lavorare dinamicamente con oggetti in cui il tipo non è noto fino al runtime. Ad esempio con OR-mappers o in un'architettura plug-in. I framework di simulazione ne fanno uso, se si desidera scrivere una libreria di logging e dinamicamente si desidera esaminare il tipo e le proprietà delle eccezioni.

Se penso un po 'più a lungo, posso probabilmente trovare altri esempi.


2
2017-09-08 13:52



Trovo che la riflessione sia molto utile se i dati di input (come xml) hanno una struttura complessa facilmente associabile a istanze di oggetti o ho bisogno di una sorta di relazione "è una" tra le istanze.

Poiché la riflessione è relativamente semplice in java, a volte la uso per dati semplici (mappe valore-chiave) in cui ho un piccolo set fisso di chiavi. Con una mano è semplice determinare se una chiave è valida (se la classe ha un setter setKey (dati String)), d'altra parte posso cambiare il tipo di dati di input (testuali) e nascondere la trasformazione (es. Cast semplice su int in getKey ()), quindi il resto dell'applicazione può fare affidamento su dati digitati correttamente. Se il tipo di alcune coppie chiave-valore cambia per un oggetto (ad es. Form int per float), devo solo cambiarlo nell'oggetto dati e nei suoi utenti ma non devo tenere a mente di controllare anche il parser . Questo potrebbe non essere un approccio ragionevole, se le prestazioni sono un problema ...


2
2017-09-08 14:46



Scrittura di dispatcher. Twisted sfrutta le capacità riflessive di Python per inviare chiamate XML-RPC e SOAP. RMI utilizza Java reflection api per la spedizione.

Analisi della riga di comando. Costruire un oggetto di configurazione in base ai parametri della riga di comando che vengono passati.

Quando si scrivono i test delle unità, può essere utile usare il reflection, sebbene in gran parte lo abbia usato per bypassare i modificatori di accesso (Java).


1
2017-09-08 13:52



Ho usato il reflection in C # quando c'era qualche metodo interno o privato nel framework o una libreria di terze parti a cui volevo accedere.

(Disclaimer: Non è necessariamente una best practice perché i metodi privati ​​e interni possono essere modificati nelle versioni successive, ma ha funzionato per quello di cui avevo bisogno.)


1
2017-09-08 13:55



Bene, in linguaggi tipizzati staticamente, dovresti usare la reflection ogni volta che devi fare qualcosa di "dinamico". È utile per gli strumenti (scansione dei membri di un oggetto). In Java è usato un po 'in JMX e proxy dinamici. E ci sono un sacco di casi unici in cui è davvero l'unica strada da percorrere (praticamente ogni volta che devi fare qualcosa che il compilatore non ti permetterà di fare).


1
2017-09-08 13:55



Generalmente utilizzo il reflection per il debugging. La riflessione può visualizzare più facilmente e con maggiore precisione gli oggetti all'interno del sistema rispetto a un assortimento di istruzioni di stampa. In molte lingue che dispongono di funzioni di prima classe, è anche possibile richiamare le funzioni dell'oggetto senza scrivere codice speciale.

C'è, tuttavia, un modo per fare ciò che vuoi (ndr). Usa una tabella hash. Memorizza i campi con chiave sul nome del campo.

Se lo si desidera, è possibile creare funzioni Get / Set standard o creare macro che lo facciano al volo. #define GetX() Get("X") genere di cose.

Potresti anche implementare la tua riflessione imperfetta in questo modo.

Per l'utente avanzato, se è possibile compilare il codice, potrebbe essere possibile abilitare la generazione di output di debug e utilizzarlo per eseguire la reflection.


1
2017-09-21 01:18