Szenarien für die Reflektionsausgabe mit dynamischen Methoden
Dynamische Methoden, die mithilfe der DynamicMethod-Klasse erstellt wurden (neu in .NET Framework, Version 2.0) bieten verbesserte Möglichkeiten der Ausgabe statischer Methoden zur Laufzeit. Dynamische Methoden erweitern den Funktionsumfang der Typen im System.Reflection.Emit-Namespace in mehrfacher Hinsicht:
Sie verursachen eine geringere Systembelastung, da keine dynamischen Assemblys, Module und Typen generiert werden müssen, die die Methoden enthalten sollen.
In Anwendungen, die über einen längeren Zeitraum ausgeführt werden, sorgen sie für eine bessere Ressourcennutzung, da der vom Methodentext verwendete Speicher zurückgefordert werden kann, wenn die Methode nicht mehr benötigt wird.
Sofern sie über ausreichende Sicherheitsberechtigungen verfügen, ermöglichen sie es, einer vorhandenen Assembly oder einem vorhandenen Typ Code zuzuordnen. Dieser Code kann die gleiche Sichtbarkeit wie interne Typen oder private Member aufweisen.
Sofern sie über ausreichende Sicherheitsberechtigungen verfügen, ermöglichen sie es, dass Code die Just-in-Time (JIT)-Sichtbarkeitsüberprüfungen überspringt und auf die privaten und geschützten Daten von Objekten zugreift.
Dynamische Methoden können mithilfe eines ILGenerator-Objekts Microsoft Intermediate Language (MSIL)-Code ausgeben. Darüber hinaus können dynamische Methoden anhand eines DynamicILInfo-Objekts mit Metadatentokens und -bereichen arbeiten, die ausgereiften Clients das Generieren eigenen MSIL-Codes ermöglichen.
Dynamische Methoden bieten sich in Szenarien an, in denen Code aus Leistungsgründen zur Laufzeit generiert werden muss. Bei den in diesem Abschnitt behandelten Beispielen geht es u. a. um Serialisierung, Zuordnung zwischen Objekten und relationalen Datenbanken, reguläre Ausdrücken, partielle Evaluierung und Compiler für Sprachen, die eine Laufzeit benötigen.
Ein einfaches Beispiel für die Generierung dynamischer Methoden finden Sie unter Gewusst wie: Definieren und Ausführen von dynamischen Methoden.
Sprachen, die spät gebundene Aufrufe unterstützen
Dynamische Methoden sind für Compilerwriter sinnvoll, wenn der Typ eines Objekts zur Kompilierungszeit nicht bekannt ist. Aufrufe der Member eines Objekts müssen zur Laufzeit aufgelöst werden, wobei häufig noch Argumentlisten bearbeitet werden müssen. Im folgenden Visual Basic-Code finden Sie ein entsprechendes Beispiel.
Sub Example(ByVal obj as Object)
' ...
obj.SomeMethod(x, y, z)
' ...
End Sub
Der Compiler muss Code zum Suchen von SomeMethod generieren, die Argumente als Array von Objekten vorbereiten und die Methode aufrufen. Die Ausführung derartiger Aufrufe mit Reflektion, anhand der InvokeMember-Methode, erbringt keine gute Leistung. Sie können die Leistung verbessern, indem Sie mithilfe von Membern des System.Reflection.Emit-Namespaces dynamische Assemblys, Module, Typen und Methoden erstellen. Dies kann jedoch das Workingset vergrößern und den Code komplizieren. Mit dynamischen Methoden kann die Implementierungsstrategie in Fällen, in denen die Signatur der dynamischen Methode mit einem vorhandenen Delegattyp übereinstimmt, effizienter gestaltet werden, da keine dynamischen Assemblys, Module oder Typen erstellt werden müssen. Mit dieser Herangehensweise erzielen Sie eine erheblich bessere Leistung als mit der InvokeMember-Methode. Die Leistung ist nicht so gut wie bei einem virtuellen Aufruf, dafür wird nur ein deutlich kleineres Workingset benötigt, da keine neuen Typen erstellt werden. Darüber hinaus können der generierte MSIL-Code und der zugeordnete systemeigene Code zurückgefordert werden, wenn sie nicht mehr benötigt werden.
Serialisierung
Dank dynamischer Methoden muss kein Code mehr für benutzerdefinierte Serialisierung und Deserialisierung geschrieben werden. Ein serialisierbarer Typ kann nach einfachen Regeln markiert werden. Dann können die Metadaten für den Typ mithilfe eines Serialisierungsmoduls untersucht und nach Bedarf ein entsprechender Serialisierer und Deserialisierer generiert werden. Anschließend wird der generierte Code für Instanzen des Typs ausgeführt.
Ein mithilfe von dynamischen Methoden implementiertes Serialisierungsmodul kann, sofern es über ausreichende Sicherheitsberechtigungen verfügt, auf private und geschützte Daten zugreifen, um die Serialisierung von Objekten, die nicht vom Modulersteller geschrieben wurden, zu ermöglichen.
Generierte Methoden können bei häufiger Verwendung zwischengespeichert oder einfach freigegeben werden.
Partielle Evaluierung
Die partielle Evaluierung, auch als Programmspezialisierung bezeichnet, ist eine Technik zur Optimierung von Algorithmen, bei denen eine oder mehrere Eingabevariablen sich seltener als andere Eingaben ändern. Bei der partiellen Evaluierung werden spezialisierte Methodenaufrufe generiert, die die Werte der seltener geänderten Eingaben als Konstanten behandeln, sodass der Algorithmus als Ganzes optimiert werden kann.
Mit diesem Verfahren können vielfältig einsetzbare Algorithmen mit geringer Leistung häufig in spezialisierte Algorithmen mit hoher Leistung umgewandelt werden. Es folgen einige Umsetzungsbeispiele:
Kompilieren eines Regex-Objekts, um ein Programm zu generieren, das auf den Abgleich mit einem besonderen Muster spezialisiert ist.
Kompilieren eines metadatengesteuerten Serialisierungsmoduls in ein Programm, das auf die Serialisierung und Deserialisierung eines bestimmten Typs bzw. einer Reihe bestimmter Typen spezialisiert ist.
Kompilieren eines XML-Schemas, um ein Programm zu generieren, das auf die Überprüfung eines besonderen Schemas spezialisiert ist.
Kompilieren einer XSLT-Transformation in ein Programm, das auf eine bestimmte Art der Transformierung eines XML-Dokuments spezialisiert ist.
Kompilieren eines generischen Verschlüsselungsprogramms, das Daten mit jedem angegebenen Schlüssel verschlüsselt, in ein Programm, das für einen bestimmten Schlüssel optimiert ist.
Die partielle Evaluierung kann mithilfe von dynamischen Methoden implementiert werden, indem zur Laufzeit spezialisierte Methoden generiert werden. Dynamische Methoden verbessern nicht nur die Leistung, sondern ermöglichen auch die Wiedergewinnung der MSIL-Methodentexte und des vom JIT-Compiler generierten zugehörigen Computercodes. Dies kann in Programmen mit langer Laufzeit von entscheidender Bedeutung sein.
Eine ausführlichere Beschreibung einiger dieser Szenarien finden Sie unter Anwendungsszenarien für die Reflektionsausgabe.
Generieren von benutzerdefiniertem Code zur Laufzeit
Viele Anwendungen oder Plattformen verfügen über Erweiterungsmechanismen, die Benutzern das Schreiben und Ausführen von eigenem Code ermöglichen, während die Anwendung ausgeführt wird. Dafür werden häufig vordefinierte Funktionen verwendet. Wenn dieser Code mithilfe dynamischer Methoden generiert wird, kann der Anwendungs- oder Plattformentwickler die Anzahl der erforderlichen Funktionen (und damit auch die Speicherbeanspruchung) vermindern. Dies gibt den Benutzern mehr Flexibilität, ohne Abstriche an der Leistung hinnehmen zu müssen.
Siehe auch
Aufgaben
Gewusst wie: Definieren und Ausführen von dynamischen Methoden
Referenz
Konzepte
Anwendungsszenarien für die Reflektionsausgabe