Wenn die Reflexion ist ineffizient, Wann ist es am geeignetsten?
Finde ich eine Menge Fälle, wo ich mir denke, dass ich verwenden könnte, relfection um ein problem zu lösen, aber ich in der Regel nicht, da höre ich viel entlang der Linien von "don' T verwenden Sie reflektion, es ist zu ineffizient".
Nun bin ich in einer position, wo ich habe ein problem, wo ich nicht finden können, eine andere Lösung als die Verwendung der Reflexion mit der new T()
wie im diese Frage & Antwort.
Also ich Frage mich, ob jemand kann mir sagen, Reflexion der spezifischen beabsichtigten Gebrauch, und wenn es gibt eine Reihe von Leitlinien zu zeigen, wenn es angebracht ist und Wann nicht?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ist es oft "schnell genug", und wenn Sie benötigen, schneller (bei engen loops etc.), die Sie tun können meta-Programmierung mit
Expression
oderILGenerator
(vielleicht überDynamicMethod
), um extrem schnellen code (darunter auch einige tricks, die Sie nicht tun können in C#).Reflexion ist mehr Häufig verwendet für die framework/Bibliothek-Szenarien, bei denen die Bibliothek per definition weiß nichts über die Anrufer, und muss, basierend auf der Konfiguration, Parametern oder Muster.
dynamic
, welche Optimierungen wie call site caching. Es gibt also eine Zwischenstufe zwischen reflection und metaprogramming. In der Tat, ich benutzedynamic
Wann immer ich kann, anstatt direkt mit der spiegelung, nur für die Lesbarkeit.Wenn es eine Sache gibt, die ich hasse hören, es ist "don' T verwenden Sie reflektion, es ist zu ineffizient".
Zu ineffizient, für was? Wenn Sie schreiben eine Konsole-Anwendung, die laufen einmal im Monat und ist nicht mal kritisch, ist es wirklich wichtig, wenn es dauert 30 Sekunden statt der 28, weil Sie mit einer Reflexion?
Richtlinien, wenn es unangemessen ist zu verwenden sind diejenigen, die nur können Sie wirklich zusammen sind Sie stark abhängig, was du tust und wie effizient/leistungsfähig alternativen sind.
Eine nützliche Abstraktion zur code-Effizienz ist die partition, auf der Sie in drei Kategorien der Zeit, die jeweils etwa 3 Größenordnungen auseinander.
Erste Mensch-Zeit. Es gibt eine Menge Sie tun können, wenn Sie müssen nur zu halten eine person glücklich mit der performance des Codes. Menschen können nicht erkennen, den Unterschied zwischen code, der braucht 10 Millisekunden und 20 Millisekunden, sehen beide instant. Und ein Mensch wird vergeben, wenn ein Programm braucht 6 Sekunden statt 5 etwa 3 Milliarden Maschine Anweisungen mehr. Gängige Beispiele für Programme, die bei human-time-Compiler und point-and-click-Designer. Mit der spiegelung ist nie ein problem.
Dann gibt es I/O-Zeit. Wenn Ihr Programm treffen muss die Festplatte oder das Netzwerk. I/O ist langsam, begrenzt durch mechanische Bewegung in den Fall von der Festplatte, die Bandbreite und die Latenz in der Falle des Netzes. Sie können immer sagen, wenn I/O ist der Flaschenhals, dein Programm läuft, ist es aber nicht fahren, bis die CPU-Last zu viel. Das Betriebssystem ist ständig blockiert der thread, so dass es warten, bis die E/A-Anforderung abgeschlossen ist.
Reflexion arbeitet bei I/O-Zeit. Zum abrufen von Daten, die CLR muss, Lesen Sie den Metadaten der assembly. Und wenn Sie das nicht getan, bevor, Ihr Programm verursacht einen page-fault, erfordert das Betriebssystem zum Lesen der Daten von der Festplatte. Was folgt, ist, dass, grob, Reflexion machen können I/O-bound-code nur doppelt so langsam. In der Regel besser, denn nachdem die erste perf-hit, der Metadaten im Cache gespeichert und abgerufen werden können, viel schneller. Reflexion ist somit oft ein annehmbarer Kompromiss. Die kanonischen Beispiele sind Serialisierung und dbase-ORMs.
Dann gibt ' s Maschine-Zeit. Die raw-Leistung von einem CPU-Kern ist wunderbar. Eine Eigenschaft getter ausgeführt werden können irgendwo zwischen 0 und 1/2 Nanosekunden. Dies gilt nicht günstig im Vergleich mit, sagen wir, PropertyInfo.GetValue(). Beide halten die CPU beschäftigt, Sie werden sehen, die CPU-Last für den core auf 100%. Aber GetValue() kostet Hunderte, wenn nicht Tausende von Computer-code-Anweisungen. Nicht eingerechnet die Zeit, die benötigt wird, um der Seite in den Metadaten. Zwar nicht viel zusätzliche Zeit, es baut sich sehr schnell, wenn Sie loop.
Wenn Sie nicht klassifizieren Sie Ihre Reflexion-code in der Mensch-time oder I/O-Zeit-Kategorien, die dann die Reflexion ist unwahrscheinlich, dass ein geeigneter Ersatz für den regulären code.
Den Schlüssel zu halten Reflexion verlangsamen Ihr Programm nicht verwenden, es in einen loop. Wenn Sie möchten, Lesen einer Eigenschaft von einem Objekt während der Start - (einmal), reflektion verwenden. Sie wollen Lesen Sie eine Eigenschaft aus einer Liste von 10.000 Objekte unbekannten Typs, reflektion verwenden, um die Eigenschaft getter-Delegierten einmal (Suchbegriff:
PropertyInfo.GetGetMethod
), dann rufe die delegate-10.000 Arten. Es gibt viele Beispiele dafür auf StackOverflow.Reflexion ist nicht ineffizient. Es ist weniger effizient als direkte Anrufe. So personnaly ich reflektion verwenden, wenn es keine entsprechende compile-Zeit sichere Methode. IMHO das problem mit der reflektion ist nicht so sehr die Leistungsfähigkeit, sondern auch die zerbrechlichkeit der code, wie es verwendet magic strings, die sind sehr umgestalten unfreundlich.
Ich benutze es für die plugin-Architektur - Blick durch Versammlungen in den plugin-Ordner für Methoden markiert mit einem benutzerdefinierten Attribut, das angibt, info über das plugin - und in ein logging-framework. Das framework erkennt ein benutzerdefiniertes Attribut für die Montage selbst, die enthält Informationen über den Autor der Versammlung, die Projekt -, versions-Informationen, und andere tags, die angemeldet sind, zusammen mit allem, was in dem stack-trace.
Gehen, zu verschenken ein 'Geschäftsgeheimnis', aber es ist gut. Das framework ermöglicht Ihnen tag jede Methode oder Klasse mit einer "Story ref', z.B.
[StoryRef(Ref="ImportCSV1")]
...und die Idee ist, dass es würde der Integration in unserem agilen Projekt-management-framework: wenn es irgendwelche Ausnahmen, die innerhalb dieser Klasse/Methode, die logging-Methode würde reflektion verwenden, um zu überprüfen, für eine
StoryRef
Attribut in der Stapel-Ablaufverfolgung, und wenn ja, dass wäre angemeldet als Ausnahme gegen die Geschichte. In der PM-software konnte man sehen, Ausnahmen von der Geschichte (eine Geschichte ist wie eine extreme/agile, use-case).Ich denke, das ist eine berechtigte Nutzung, mindestens! Im Grunde, wenn es nur scheint, die meisten ordentlich und geeignet Weg, es zu tun, ich benutze Reflexion. Nichts anderes kommt wirklich in ihn - ich kann nicht denken Sie an eine Gelegenheit, die Sie sein würde, mit Reflexion zu machen, dass viele Anrufe, die Effizienz zu kommen.
Einen bad Beispiel der Reflexion ist dies eine aus Wikipedia:
Hier, es gibt keinen Vorteil zum verwenden der Reflexion: Die nicht-Reflexion-unter Verwendung von code ist nicht nur effizienter, aber einfacher zu verstehen.
Gute verwendet der Reflexion sind Dinge wie die Serialisierung und Objekt-relationale-mapping, die sind einfach zu implementieren, wenn Sie haben eine Liste von einer Klasse Eigenschaften, aber sonst nur über eine benutzerdefinierte Funktion, die für jede Klasse.