Frage

Was genau ist Reflexion? Ich lese den Wikipedia-Artikel zu diesem Thema und ich verstehe, dass es sich um eine Art Meta-Programmierung ist, wenn das Programm selbst zur Laufzeit ändern kann, aber etwas bedeutet das? In welcher Art von Situationen ist dies ein guter Ansatz und wann ist es die beste, es zu benutzen?

War es hilfreich?

Lösung

Die Reflexion ist eine Einrichtung, in der Sie ein Objekt über seine Attribute zur Laufzeit abfragen. Zum Beispiel, Python, Java und .Net haben Einrichtungen, in denen Sie die Instanzvariablen oder Methoden eines Objekts finden.

Ein Beispiel einer Anwendung für die Reflexion ist eine O / R-Mapping-Schicht. Einige verwenden Reflexion um ein Objekt zu konstruieren, indem seine Eigenschaften während der Laufzeit und eine Instanz Quering dynamisch Bestücken. Auf diese Weise können Sie dies anhand von Metadaten aus einer Art von Datenwörterbuch programmatisch tun, ohne die Anwendung neu zu kompilieren.

ein einfaches Beispiel zu nehmen, werde ich Python verwenden, weil seine Reflexion Einrichtungen sind sehr einfach und weniger vorformulierten als die von Java oder .Net einbeziehen können.

ActivePython 2.5.2.2 (ActiveState Software Inc.) based on
Python 2.5.2 (r252:60911, Mar 27 2008, 17:57:18) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class foo:
...     def __init__(self):
...             self.x = 1
...
>>> xx = foo()      # Creates an object and runs the constructor
>>> xx.__dict__     # System metadata about the object
{'x': 1}
>>> a = xx.__dict__ # Now we manipulate the object through 
>>> a['y'] = 2      # its metadata ...
>>> print xx.y      # ... and suddenly it has a new instance variable
2                   
>>>

Jetzt haben wir grundlegende Reflexion zu untersuchen, die Instanzvariablen eines beliebigen Objekts verwendet. Die spezielle Variable __dict__ auf Python ist eine System-Eigenschaft eines Objekts, das eine Hash-Tabelle der Mitglieder verkeilen durch die Variable (oder Methode) Namen hat. Wir haben untersucht, reflexiv das Objekt und verwendet, um die Reflexionseinrichtungen künstlich eine zweite Instanz Variable Sack hinein, die wir dann durch den Aufruf es als Instanz Variable angezeigt werden können.

Beachten Sie, dass dieser besondere Trick nicht auf Java oder .Net funktioniert, wie die Instanzvariablen festgelegt sind. Das Typsystem dieser Sprachen erlaubt keine neue Instanz Variablen zur Laufzeit in der Art und Weise hinzugefügt werden, dass Pythons ‚Ente‘ Typisierungssystem der Fall ist. Allerdings hätte man reflexiv den Wert einer Instanzvariablen aktualisiert, die in der Typdefinition deklariert wurde.

Sie können auch Reflexion verwenden, um dynamisch Verfahren Anrufungen zu konstruieren und verschiedene andere nette Tricks wie instanziieren ein Objekt auf einem Parameter basiert auszuführen. wenn Sie irgendeine Art von Plugin-basiertem System, in der bestimmten Fähigkeiten waren optional haben, konnte man zum Beispiel verwendet Reflexion das Plugin über abzufragen, welche Dienste sie angeboten (vielleicht durch die Abfrage, ob bestimmte Schnittstellen implementiert wurden) ohne explizite Metadaten erforderlich ist.

Viel dynamische Sprache Schnittstellen wie OLE-Automatisierung verwendet Reflexion als integralen Bestandteil der Schnittstelle.

Andere Tipps

Es ist nicht so viel Modifizieren Code zur Ausführungszeit, sondern Objekte untersucht und bittet sie, Code auszuführen, ohne ihren Typen statisch zu kennen.

Eine einfache Möglichkeit zu beschreiben, wäre es „eine etwas schmerzhafte Art und Weise zur Herstellung einer statisch typisierten Sprache dynamisch verhalten.“

EDIT: Verwendung:

  • Konfiguration (zum Beispiel eine XML-Datei übernehmen, welche Typen und Eigenschaften gibt, dann geeignete Objekte konstruieren)
  • Testing (Unit-Tests, die mit Namen identifiziert werden oder Attribute)
  • Web-Services
  • (in .NET zumindest im Kern Web-Service-Engine viel Reflexion verwendet)
  • Automatische Ereignis Verkabelung - eine Methode mit einem geeigneten Namen, z SubmitButton_Click und ASP.NET wird diese Methode als Handler für das SubmitButton des Click Ereignis zuordnen (wenn Sie eingeschaltet haben autowiring)

Ist es eine gute Idee? Nun, nur dann, wenn die Alternativen sind schmerzhaft. Ich ziehe es statische Typisierung, wenn es nicht in die Quere kommen - Sie dann eine Menge Kompilierung-Güte bekommen, und es ist zu schneller. Aber wenn man tun es brauchen, Reflexion können Sie verschiedene Dinge tun, die sonst wäre einfach nicht möglich sein.

Die erste gute Beispiel, das ich von aus der Spitze von meinem Kopf denken kann, ist, wenn Sie eine Reihe von Methoden, die auf ein bestimmtes Objekt ausführen müssen, ohne zu Kompilierung-Zeit zu wissen, welche Methoden werden in ihm existieren.

Nehmen Sie Unit-Test-Frameworks zum Beispiel. Die Testläufer-Klasse, die für die Ausführung von all Unit-Tests verantwortlich ist nicht weiß, vor der Zeit, was Sie vorhaben, Ihre Methoden zu nennen. es weiß nur, dass sie mit „test“ vorangestellt werden (oder in Java 5 Fall, mit @Test kommentierte). Also, wenn eine Testklasse gegeben, reflektiert es auf dieser Klasse, um eine Liste aller Methoden in ihm zu bekommen. Dann wird iteriert durch diese Methodennamen als Strings und ruft diese Methoden auf dem Objekt, wenn sie mit „test“ beginnen. Das wäre ohne Reflexion nicht möglich. Und das ist nur ein Beispiel.

Reflection hat mir in mindestens 1 Projekt nützlich ich mir vorstellen kann. Wir schrieben ein internes „Process Manager“ Programm, das viel wichtigen Geschäftsprozesse in bestimmten Intervallen durchführt. Das Projekt ist so angelegt, dass der Kern wirklich nur ein Windows-Dienst mit Timer-Objekten, die alle 30 Sekunden oder so abfeuern und überprüfen Sie die Arbeit zu tun.

Die eigentliche Arbeit wird in einer Klassenbibliothek durchgeführt werden (entsprechend dem Namen „WorkerLib“). Wir definieren Klassen mit öffentlichen Methoden, die bestimmte Aufgaben ausführen (Dateien um, Hochladen von Daten an entfernten Standorten zu bewegen, etc.) Die Idee ist, dass der Kern Service-Methoden aus der Arbeiter-Bibliothek aufrufen können, ohne sich um die Methoden zu wissen, alles, was es anruft. Dies ermöglicht es uns, einen Zeitplan in der Datenbank für Arbeitsplätze zu schaffen, und auch neue Methoden in die Klassenbibliothek hinzufügen, ohne jemals das Core-System ändern zu müssen.

Die Grundidee ist, dass wir Reflexion im Kern Dienst verwenden können Methoden ausgeführt werden, deren Namen wir in der Datenbank gespeichert sind, definieren die Zeitpläne. Es ist recht ordentlich in der Praxis. Unsere Kernleistung ist solide und Griffe Ausführung der Aufträge nach Bedarf, während die eigentliche Arbeiter Bibliothek erweitert werden kann und bei Bedarf ohne den Kern selbst fürsorglich geändert.

Wenn Sie weitere Erklärungen benötigen, zögern Sie nicht zu fragen. Das war einfach der beste Weg, die ich denken könnte reales Szenario zu erklären, wo Reflexion wirklich die Dinge einfacher für uns macht.

Ein weiteres Beispiel: Ich habe Code, den ich verwende, dass die Ausgabe einer Datenbank übernimmt - die eine Reihe von Zeilen mit benannten Spalten ist - und führt sie in eine Reihe von Objekten. Ich iterieren durch die Reihen, und wenn das Zielobjekt eine Eigenschaft mit dem gleichen Namen und Typ hat, habe ich es. Dies macht für meine Daten-getting-Code nur etwas wie folgt aussehen:

SqlDataReader sdr = Helper.GetReader("GetClientByID", ClientID);
Client c = new Client();
FillObject(sdr, c);
return c;

Wirklich, Reflexion sollte als eine Art Verstärker für Code gedacht werden. Es kann gut Code besser und sauberer, und schlechten Code schlechter. Was tut es? Es erlaubt Ihnen, wirklich, Code zu schreiben, dass Ihr nicht ganz sicher, was es an der Zeit, die Sie schreiben, tun wird. Sie haben eine allgemeine Idee, aber es erlaubt Ihnen nicht kodieren, welche Objekte, Methoden und Eigenschaften werden ausgeführt, wenn das Programm kompiliert wird.

Weitere Beiträge sind korrekt, wenn sie sagen, dass es den Programmcode auf Konfigurationswerte basierend auszuführen erlaubt, aber es ist wirkliche Macht ist, dass es Ihnen schwer erlaubt, die Regeln der objektorientierten Programmierung zu biegen. Das ist wirklich das, was es tut. Es ist eine Art, wie die Sicherheitsmaßnahmen auszuschalten. Private Methoden und Eigenschaften können zusammen mit fast allem anderen durch Reflexion zugegriffen werden.

Ein hervorragendes Beispiel, wenn MS Reflexion verwendet, ist mit den Daten auf Datenobjekt zu binden. Sie geben den Namen des Textfeldes und Datenfeldes für ein Objekt in einem Dropdown-Liste zu binden, usw., und der Code reflektiert das Objekt und die entsprechenden Informationen herauszieht. Die Datenbindung Objekt hat den gleichen Prozess immer und immer wieder, aber es weiß nicht, welche Art von Objekt, um es mit zu binden. Reflexion ist ein bequemer Weg, ein wenig Code schreiben, um alle möglichen Fälle zu behandeln.

In Java ist es im Grunde eine Möglichkeit, eine Klasse zu instanziieren, ohne vorher darüber zu wissen. Sagen Sie bitte die Benutzer wollen, indem Sie die Klasse, um eine Konfigurationsdatei ändern können sie Ihr Programm verwenden möchten (sagen Sie zahlreiche Implementierungen einiger Schnittstelle). Mit Reflexion können Sie ein Objekt erstellen, basierend auf sie nur den Namen, die Methodensignatur, usw.. . und wirft es dann auf Ihre Schnittstelle.

Die Reflexion ist für Laufzeitkonfiguration nützlich, Teile eines Systems ermöglicht durch externe Konfiguration betrieben werden.

Zum Beispiel kann eine Klasse Fabrik verschiedene Betonart basierend auf einer Eingabedatei konstruieren könnte, wo die konkreten Typen unterschiedliche Konfigurationsinformationen benötigen eher einen konkreten Konstruktor aufzurufen als eine Builder-Schnittstelle. (Die Konstruktor-Methode des Objekts wird unter Verwendung von Reflexion befindet).

Die Reflexion ist (im Grunde) die Fähigkeit eines Programms für Typ-Informationen abzufragen, die den Compiler zur Verfügung standen. So zum Beispiel der Namen eines Typs angegeben Sie für die Methoden abfragen können es enthält. Dann gilt für jede Methode können Sie die Typen der Parameter abfragen, sie nehmen etc etc etc.

Es ist nützlich für die Laufzeitkonfiguration, wo Sie eine Konfigurationsdatei haben, die das Verhalten Ihrer Anwendung angibt. Die Konfiguration kann den Namen von konkreten Typen enthält, die Sie (wie es oft der Fall mit IOC-Containern) verwendet werden sollen. Mit Reflexion können Sie eine Instanz dieser konkreten Typ erstellen (über eine Reflexion API) und verwenden.

Ich gebe Ihnen ein Beispiel.

Als Programmierübung ich eine MP3-Datei checker schrieb. Es scannt meine Musikbibliothek und zeigt die id1 / ID2-Tags ich in einem Datagridview interessiert bin. Ich benutze Reflexion die Eigenschaften aus der MP3-Info-Klasse zu erhalten, ohne den UI-Code mit etwas über diese Klasse kennen. Wenn ich ändern möchten, welche Informationen angezeigt bekommt Ich kann entweder die MP3-Info-Klasse bearbeiten oder seine Konfiguration ändern (je nachdem, wie ich die Klasse geschrieben) und müssen nicht die Benutzeroberfläche aktualisieren.

Es bedeutete auch, dass ich in der Lage gewesen, Dependency Injection zu verwenden, um das gleiche von Ende zu verwenden, um Informationen über digitale Fotos durch Vertauschen der Datenbibliothek Klasse nur angezeigt werden soll.

Baugruppen enthalten Module, Module enthalten Typen und Arten enthalten Mitglieder. Reflection bietet Objekte, Baugruppen, Module und Typen einzukapseln. Sie können Reflektion verwenden, um dynamisch eine Instanz eines Typs zu erstellen, um den Typen zu einem bestehenden Objekt binden, oder die Art von einem vorhandenen Objekt erhalten. Anschließend können Sie den Typ der Methoden aufrufen oder ihre Felder und Eigenschaften zugreifen. Typische Anwendungen von Reflexion gehören die folgenden:

  • Verwendung Assembly zu definieren und Lastanordnungen, Lademodule, die in der Baugruppe manifest aufgelistet sind, und einen Typ aus dieser Anordnung lokalisieren und eine Instanz davon erstellen.
  • Verwenden Sie Module zu Informationen wie die Montage zu entdecken, die das Modul und die Klassen in das Modul enthält. Sie können auch alle globalen Methoden oder andere spezifische, nicht globale Methoden auf dem Modul definiert erhalten.
  • Verwenden Sie ConstructorInfo Informationen wie den Namen zu entdecken, Parameter, Zugriffsmodifikatoren (wie öffentlich oder privat) und Implementierungsdetails (wie abstrakt oder virtuell) von einem Konstruktor. Verwenden Sie die GetConstructors oder GetConstructor Methode eines Typ einen bestimmten Konstruktor aufzurufen.
  • Verwenden Sie Method um Informationen wie den Namen, Rückgabetyp, Parameter, Zugriffsmodifikatoren (wie öffentlich oder privat) und Implementierungsdetails (wie abstrakt oder virtuell) eines Verfahrens zu entdecken. Verwenden Sie die GetMethods oder GetMethod Methode eines Typ mit einer spezifischen Methode aufzurufen.
  • Verwenden Fieldinfo zu entdecken Informationen wie der Name, Zugriffsmodifikatoren (wie öffentlich oder privat) und Implementierungsdetails (wie statisch) ein Feld, und zu erhalten oder setzen Feldwerte.
  • Verwenden Eventinfo entdecken Informationen wie den Namen, Event-Handler-Datentyp, benutzerdefinierte Attribute, Typ deklarieren, und reflektiert Art eines Ereignisses, und hinzuzufügen, oder Event-Handler zu entfernen.
  • Verwenden Property Informationen wie Name, Datentyp, erklärt Art, die sich Art zu entdecken und schreibgeschützt oder beschreibbaren Zustand einer Immobilie und zu erhalten oder setzen Eigenschaftswerte.
  • Verwendung Parameterinfo entdecken Informationen wie der Name des Parameters, Datentyp, ob ein Parameter ein Eingabe- oder Ausgabeparameter ist, und die Position des Parameters in einer Methodensignatur.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top