.NET bietet mit der Reflection-API eine einfache Möglichkeit, zur Laufzeit auf Typen und deren Elemente zuzugreifen. Typische Anwendungsfälle sind die Serialisierung und die Deserialisierung von Objekten. Bei der Serialisierung werden mit Hilfe der Reflection-API alle relevanten Felder und Eigenschaften eines Objektes in eine speicherbare Form wie JSON oder XML überführt. Die Deserialisierung stellt ein Objekt aus dieser speicherbaren Form wieder her.
Der Preis für das späte Binden von Typen und Elementen zur Laufzeit ist eine geringere Performance. Operationen, die normalerweise durch den Compiler erledigt werden, müssen bei Verwendung der Reflection-API zur Laufzeit erfolgen.
Liersch.Reflection
verbessert die Performance der Reflection-API signifikant, indem für Konstruktor- und Funktionsaufrufe, sowie für Feldzugriffe dynamischer IL-Code erzeugt wird. Die Zugriffsgeschwindigkeit gleicht dadurch fast einem Direktzugriff. Es werden alle wichtigen .NET-Plattformen unterstützt (ab .NET Framework 2.0, ab .NET Core 2.0 und ab .NET Standard 2.1). Für ältere Projekte (vor .NET Framework 4.0) muss die Bibliothek manuell kompiliert und integriert werden.
Die Qualität der Bibliothek wird durch automatisierte Modultests sichergestellt. Für relevante Funktionen sind Modultests hinterlegt. Alle wesentlichen Bibliotheksänderungen werden in der Datei CHANGELOG.md protokolliert.
Features
Liersch.Reflection
ist auf die Serialisierung und Deserialisierung von Objekten spezialisiert und stellt dafür die folgenden Features bereit:
- schnelle Erzeugung von Klassen mit Hilfe des Standardkonstruktors
- schnelle Erzeugung von Wertetypen
- schnelles Aufrufen von Funktionen
- schnelles Lesen und Schreiben von Eigenschaften
- schnelles Lesen und Schreiben von Feldern
Die Bibliothek ist in C# 6.0 geschrieben. Die Dateigröße der kompilierten Bibliothek beträgt lediglich ≈20 kB.
Beispiel
Die Beispielanwendung verwendet Liersch.Profiling, um die Performance verschiedener Szenarien miteinander zu vergleichen. Die Messergebnisse zeigen den Geschwindigkeitsvorteil, der mit Liersch.Reflection
erzielt werden kann. Die Performancemessung sollte außerhalb der Entwicklungsumgebung und auf Basis der Release-Version durchgeführt werden. Andernfalls beeinflusst der für das Debugging notwendige Zusatzaufwand das Messergebnis.
Integration
Liersch.Reflection
beinhaltet die Klasse Accelerator
, mit deren Hilfe Funktionszeiger für die schnelle Erzeugung von Typen, das schnelle Aufrufen von Funktionen und das schnelle Lesen und Schreiben von Eigenschaften und Feldern erzeugt werden können.
Statt Objekte mit Activator.CreateInstance
zu erzeugen, muss nun der von Accelerator.CreateStandardConstructor
gelieferte Funktionszeiger benutzt werden, um neue Instanzen zu erzeugen.
Func0 create=Accelerator.CreateStandardConstructor(type);
// ...
object inst=create();
Des Weiteren stehen einige ausgewählte Funktionen der Accelerator
-Klasse alternativ als Erweiterungsfunktionen mit einer vereinfachten Signatur zur Verfügung.
InvocationDelegate toLower=typeof(string).CreateInvocationDelegate("ToLowerInvariant");
// ...
object o=toLower("Hello World!");
Für Funktionen mit bis zu zwei Parametern sind spezialisierte Funktionen verfügbar, die für die Parameterübergabe kein Array verwenden. Wenn nicht statische Funktionen aufgerufen werden, repräsentiert der erste Parameter stets die zu verwendende Instanz. Für die Manipulation von Wertetypen müssen diese vorher durch Boxing in den Heap-Speicher befördert werden (z. B. durch Typumwandlung nach object
). Nur so ist sichergestellt, dass die Manipulationsfunktionen stets das gleiche Objekt bearbeiten und nicht bei jedem Zugriff eine neue Kopie verwenden. Eine Unterstützung von per Verweis übergebenen Parametern (siehe Schlüsselwort ref
und out
) ist nicht vorgesehen.
Die Verbesserung der Performance von Reflection-basierten Zugriffen erfolgt auf Basis von dynamisch generiertem Code. Der Aufwand der Codegenerierung lohnt sich nur dann, wenn eine höhere Anzahl von Zugriffen erwartet wird.
Lizenz
Die Veröffentlichung der Software erfolgt unter den Bedingungen einer Open-Source-Lizenz. Alternativ können im Rahmen einer kommerziellen Lizenz andere Bedingungen vereinbart werden. Sie können Pflege und Weiterentwicklung der Software mit einer freiwilligen Spende unterstützen.
Copyright
Copyright © 2020-2021 Steffen Liersch
https://www.steffen-liersch.de/
Verweise
Der Quellcode wird auf GitHub gepflegt:
https://github.com/steffen-liersch/Liersch.Reflection
Pakete können über NuGet heruntergeladen werden:
https://www.nuget.org/packages/Liersch.Reflection
Schreiben Sie einen Kommentar
Sie müssen angemeldet sein, um einen Kommentar abzugeben.