Frage

Kürzlich habe ich mit einem Kollegen über C++ gesprochen und mich darüber beklagt, dass es keine Möglichkeit gibt, einen String mit dem Namen eines Klassenfelds zu nehmen und das Feld mit diesem Namen zu extrahieren;mit anderen Worten, es mangelt an Reflexion.Er warf mir einen verwirrten Blick zu und fragte, wann jemand jemals so etwas tun müsste.

Auf den ersten Blick hatte ich keine gute Antwort für ihn außer „Hey, ich muss es sofort tun“.Also habe ich mich hingesetzt und eine Liste einiger Dinge erstellt, die ich tatsächlich mit Reflexion in verschiedenen Sprachen gemacht habe.Leider stammen die meisten meiner Beispiele aus meiner Webprogrammierung in Python und ich hatte gehofft, dass die Leute hier mehr Beispiele hätten.Hier ist die Liste, die ich erstellt habe:

  1. Gegeben sei eine Konfigurationsdatei mit Zeilen wie
    x = „Hallo Welt!“
    y = 5,0
    Legen Sie die Felder einiger dynamisch fest config Objekt gleich den Werten in dieser Datei.(Ich wünschte, ich könnte dies in C++ tun, konnte es aber tatsächlich nicht.)

  2. Wenn Sie eine Liste von Objekten sortieren, sortieren Sie sie basierend auf einem beliebigen Attribut, indem Sie den Namen dieses Attributs aus einer Konfigurationsdatei oder einer Webanforderung angeben.

  3. Wenn Sie Software schreiben, die ein Netzwerkprotokoll verwendet, können Sie mit Reflection Methoden aufrufen, die auf Zeichenfolgenwerten aus diesem Protokoll basieren.Ich habe zum Beispiel einen IRC-Bot geschrieben, der übersetzen würde
    !some_command arg1 arg2
    in einen Methodenaufruf actions.some_command(arg1, arg2) und alles, was diese Funktion zurückgegeben hat, an den IRC-Kanal zurückgeben.

  4. Bei der Verwendung der __getattr__-Funktion von Python (die so etwas wie method_missing in Ruby/Smalltalk ist) habe ich mit einer Klasse mit vielen Statistiken gearbeitet, wie zum Beispiel late_total.Für jede Statistik wollte ich _percent hinzufügen können, um diese Statistik als Prozentsatz der Gesamtzahl der Dinge zu erhalten, die ich gezählt habe (z. B. stats.late_total_percent).Reflexion machte dies sehr einfach.

Kann hier jemand Beispiele aus seinen eigenen Programmiererfahrungen nennen, in denen Reflexion hilfreich war?Wenn mich das nächste Mal ein Kollege fragt, warum ich „so etwas jemals machen möchte“, möchte ich besser vorbereitet sein.

War es hilfreich?

Lösung

Zur Reflexion kann ich folgende Verwendung auflisten:

  • Späte Bindung
  • Sicherheit (Introspect-Code aus Sicherheitsgründen)
  • Code-Analyse
  • Dynamisches Tippen (Duck-Typing ist ohne Reflexion nicht möglich)
  • Metaprogrammierung

Einige praktische Anwendungen der Reflexion aus meiner persönlichen Erfahrung:

  • Entwickeltes Plugin-System basierend auf Reflexion
  • Verwendetes aspektorientiertes Programmiermodell
  • Statische Codeanalyse durchgeführt
  • Verwendet verschiedene Dependency-Injection-Frameworks
  • ...

Reflexion ist eine gute Sache :)

Andere Tipps

Ich habe Reflection verwendet, um aktuelle Methodeninformationen für Ausnahmen, Protokollierung usw. abzurufen.

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

anstatt

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

Es ist einfach einfacher, die Vererbung durch Kopieren/Einfügen und die Codegenerierung durchzuführen.

Ich befinde mich jetzt in einer Situation, in der ein XML-Stream über die Leitung eingeht und ich ein Entity-Objekt instanziieren muss, das sich selbst aus Elementen im Stream füllt.Es ist einfacher, mithilfe der Reflektion herauszufinden, welches Entity-Objekt welches XML-Element verarbeiten kann, als eine gigantische, wartungsintensive Bedingungsanweisung zu schreiben.Es besteht eindeutig eine Abhängigkeit zwischen dem XML-Schema und der Art und Weise, wie ich meine Objekte strukturiere und benenne, aber ich kontrolliere beides, sodass es kein großes Problem darstellt.

Es kommt häufig vor, dass Sie Objekte dynamisch instanziieren und mit ihnen arbeiten möchten, deren Typ erst zur Laufzeit bekannt ist.Zum Beispiel mit OR-Mappern oder in einer Plugin-Architektur.Mocking-Frameworks verwenden es, wenn Sie eine Protokollierungsbibliothek schreiben und Typ und Eigenschaften von Ausnahmen dynamisch untersuchen möchten.

Wenn ich etwas länger nachdenke, fallen mir wahrscheinlich noch mehr Beispiele ein.

Ich finde Reflexion sehr nützlich, wenn die Eingabedaten (wie XML) eine komplexe Struktur haben, die sich leicht auf Objektinstanzen abbilden lässt, oder wenn ich eine Art „ist ein“-Verhältnis zwischen den Instanzen benötige.

Da die Reflektion in Java relativ einfach ist, verwende ich sie manchmal für einfache Daten (Schlüssel-Wert-Maps), bei denen ich über einen kleinen festen Schlüsselsatz verfüge.Einerseits ist es einfach zu bestimmen, ob ein Schlüssel gültig ist (wenn die Klasse einen Setter setKey(String data) hat), andererseits kann ich den Typ der (textuellen) Eingabedaten ändern und die Transformation ausblenden (z. B. einfache Umwandlung). zu int in getKey()), sodass sich der Rest der Anwendung auf korrekt typisierte Daten verlassen kann.Wenn sich der Typ eines Schlüssel-Wert-Paares für ein Objekt ändert (z. B.form int to float), muss ich es nur im Datenobjekt und seinen Benutzern ändern, muss aber nicht daran denken, auch den Parser zu überprüfen.Dies ist möglicherweise kein sinnvoller Ansatz, wenn die Leistung ein Problem darstellt ...

Disponenten schreiben.Twisted nutzt die Reflexionsfunktionen von Python, um XML-RPC- und SOAP-Aufrufe zu versenden.RMI verwendet für den Versand die Reflection-API von Java.

Befehlszeilenanalyse.Erstellen eines Konfigurationsobjekts basierend auf den übergebenen Befehlszeilenparametern.

Beim Schreiben von Unit-Tests kann es hilfreich sein, Reflection zu verwenden, obwohl ich dies meistens verwendet habe, um Zugriffsmodifikatoren (Java) zu umgehen.

Ich habe Reflection in C# verwendet, wenn es im Framework oder in einer Drittanbieterbibliothek eine interne oder private Methode gab, auf die ich zugreifen wollte.

(Haftungsausschluss:Dies ist nicht unbedingt eine Best Practice, da private und interne Methoden in späteren Versionen möglicherweise geändert werden.Aber es hat für das funktioniert, was ich brauchte.)

Nun, in statisch typisierten Sprachen möchten Sie die Reflexion immer dann verwenden, wenn Sie etwas „Dynamisches“ tun müssen.Es ist praktisch für Werkzeugzwecke (Scannen der Mitglieder eines Objekts).In Java wird es häufig in JMX und dynamischen Proxys verwendet.Und es gibt unzählige Einzelfälle, in denen dies wirklich der einzige Weg ist (so ziemlich immer dann, wenn Sie etwas tun müssen, das der Compiler nicht zulässt).

Im Allgemeinen verwende ich Reflection zum Debuggen.Reflection kann die Objekte innerhalb des Systems einfacher und genauer anzeigen als eine Reihe von Druckanweisungen.In vielen Sprachen mit erstklassigen Funktionen können Sie die Funktionen des Objekts sogar aufrufen, ohne speziellen Code schreiben zu müssen.

Es gibt jedoch eine Möglichkeit, das zu tun, was Sie wollen.Verwenden Sie eine Hashtabelle.Speichern Sie die Felder verschlüsselt anhand des Feldnamens.

Wenn Sie es wirklich wollten, könnten Sie dann Standard-Get/Set-Funktionen erstellen oder Makros erstellen, die dies im laufenden Betrieb erledigen. #define GetX() Get("X") So etwas.

Sie könnten auf diese Weise sogar Ihr eigenes unvollkommenes Spiegelbild umsetzen.

Wenn Sie als fortgeschrittener Benutzer den Code kompilieren können, ist es möglicherweise möglich, die Generierung der Debug-Ausgabe zu aktivieren und diese für die Reflektion zu verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top