Perché è raccomandato l’uso di reflection in .NET?

È sicuramente una buona pratica usarlo?

Quali sono alcune possibili situazioni in un progetto che necessita di riflessione?

Il valore principale di Reflection è che può essere utilizzato per ispezionare assiemi, tipi e membri. È uno strumento molto potente per determinare il contenuto di un assieme o un object sconosciuto e può essere utilizzato in un’ampia varietà di casi.

Gli oppositori di Reflection citeranno che è lento, il che è vero se confrontato con l’esecuzione di codice statico – tuttavia Reflection è usato in tutto il framework .NET e, a condizione che non sia abusato, può essere uno strumento molto potente nel toolkit.

Alcune utili applicazioni:

  • Determinazione delle dipendenze di un assembly

  • I tipi di posizione che si conformano a un’interfaccia, derivano da una class base / astratta e cercano i membri per attributi

  • (Smelly) testing – Se dipendi da una class che non è testabile (cioè non ti permette di build facilmente un falso) puoi usare Reflection per iniettare valori falsi all’interno della class – non è carino, e non raccomandato, ma può essere uno strumento utile in un vicolo cieco.

  • Debugging – scaricare un elenco degli assembly caricati, i loro riferimenti, i metodi correnti, ecc …

Ci sono molti usi per la riflessione:

  1. Iterazione delle proprietà in un object.
  2. Richiamo di un metodo definito in fase di esecuzione.
  3. Molti altri sulla stessa vena.

Tuttavia, uno dei miei usi preferiti della riflessione è trovare proprietà che sono state contrassegnate con attributi.

Ad esempio, ho scritto degli attributi che indicano quali proprietà delle mie classi dovrebbero essere indicizzate usando Lucene. In fase di esecuzione, posso esaminare qualsiasi class e capire quali campi devono essere indicizzati semplicemente interrogando la class per le proprietà “contrassegnate”.

La riflessione è solo un modo per indagare sugli oggetti durante l’esecuzione. Non dovresti usarlo se non hai bisogno di farlo.

Reflection consente a un’applicazione di raccogliere informazioni su se stessa e anche di manipolare su se stessa. Può essere utilizzato per trovare tutti i tipi in un assieme e / o richiamare dynamicmente i metodi in un assieme.

System.Reflection: namespace contiene le classi e le interfacce che forniscono una vista gestita di tipi, metodi e campi caricati, con la capacità di creare e invocare dynamicmente i tipi; questo processo è noto come Reflection in .NET framework.

System.Type: class è la class principale per la funzionalità .NET Reflection ed è il modo principale per accedere ai metadati. La class System.Type è una class astratta e rappresenta un tipo nel Common Type System (CLS).

Rappresenta le dichiarazioni di tipo: tipi di classi, tipi di interfaccia, tipi di array, tipi di valore, tipi di enumerazione, parametri di tipo, definizioni di tipi generici e tipi generici costruiti aperti o chiusi.

Per esempio:

using System; using System.Reflection; static class ReflectionTest { public static int Height; public static int Width; public static int Weight; public static string Name; public static void Write() { Type type = typeof(ReflectionTest); // Get type pointer FieldInfo[] fields = type.GetFields(); // Obtain all fields foreach (var field in fields) // Loop through fields { string name = field.Name; // Get string name object temp = field.GetValue(null); // Get value if (temp is int) // See if it is an integer. { int value = (int)temp; Console.Write(name); Console.Write(" (int) = "); Console.WriteLine(value); } else if (temp is string) // See if it is a string. { string value = temp as string; Console.Write(name); Console.Write(" (string) = "); Console.WriteLine(value); } } } } class Program { static void Main() { ReflectionTest.Height = 100; // Set value ReflectionTest.Width = 50; // Set value ReflectionTest.Weight = 300; // Set value ReflectionTest.Name = "ShekharShete"; // Set value ReflectionTest.Write(); // Invoke reflection methods } } Output Height (int) = 100 Width (int) = 50 Weight (int) = 300 Name (string) = ShekharShete 

Ad esempio, è ansible utilizzare la riflessione per implementare un sistema di plug-in. Basta cercare tutte le DLL in una cartella e attraverso il reflection control se implementano una certa interfaccia plugin. Questo è lo scopo principale per il quale ho usato la reflection, ma l’ho anche usato per implementare una serializzazione generica di oggetti home-brew, in cui le prestazioni non erano la più grande preoccupazione.

Come accennato in precedenza, le prestazioni avranno un successo.

Un altro grande vantaggio è che è ansible caricare in modo dinamico gli assiemi, eseguire la manipolazione delle proprietà anche se non si ha la possibilità di vedere cosa cambiare, ecc.

Le ragioni per usare questo sono molte. Ecco un’introduzione se hai bisogno.

Reflection è comunemente usato nei contenitori IoC. Diciamo che vuoi registrare ogni class concreta al termine con la parola “Controller”. La riflessione lo rende un pezzo di torta.

Ho anche usato il reflection per manipolare i campi privati ​​durante le lezioni di testing unitario.

L’utilissima class XmlSerialization si basa sulla riflessione. Non devi affrontare te stesso la riflessione per usare la serializzazione, le classi di serializzazione invocano la riflessione da sole. Ma aiuta a taggare il tuo codice con Attributi che guidano il modo in cui gli oggetti sono serializzati. Le classi di serializzazione utilizzano la reflection al runtime per leggere quegli attributi. Alla fine, il processo sembra quasi magico, richiedendo pochissime righe di codifica esplicita in un’applicazione; è la riflessione che rende ansible questa comodità.

XmlSerialization è impressionante non solo perché è un modo molto conveniente per creare file di dati da un’applicazione, ma è anche un mezzo molto semplice per generare record leggibili dal punto di vista del modello di dati interni di un programma a scopo di debug.

Venendo dal C ++ e avendo bisogno di alcune semplici gerarchie di classi, posso dire che la parola chiave è inestimabile!

 class MenuItem : Item { } foreach(Item items in parent.ChildItems) { if (item is MenuItem) { /* handle differently */ } } 

PS La riflessione non è leggermente costosa, btw?