Reflection
Aus Das Sopra Wiki
Mit Reflection kann ein Programm Kenntnisse über die eigene Struktur oder über die Struktur eines anderen Programmes erlangen. Dadurch wird es zum Beispiel möglich, eine Plug-In Architektur extrem einfach aufzubauen.
Inhaltsverzeichnis |
Klassen
Um eine Klasse zu untersuchen braucht man als erstes deren Typ. Dieser wird durch eine Instanz der Klasse Type[1] repräsentiert. Sie stellt die folgenden, für uns interessanten Methoden zur Verfügung:
- GetMethods()
- Gibt alle öffentlichen Methoden einer Klasse zurück. Diese werden durch MethodInfo[2]-Objekte beschrieben.
- GetMethod(String methodName)
- Gibt eine Methode, die durch einen Namen spezifiziert wurde zurück.
- GetProperty(String name) und GetProperties()
- Das Gleiche für Properties.
- GetField(String name) und GetFields()
- Das Gleiche für Felder
- GetInterface(String name) und GetInterfaces()
- Das Gleiche für Interfaces, die die Klasse implementiert.
Es gibt mehrere Möglichkeiten, um eine Type-Instanz zu bekommen:
1. Wenn man die Klasse kennt, aber jetzt noch kein Objekt erzeugen möchte, kann man das typeof-Schlüsselwort verwenden:
Type t = typeof(String);
2. Wenn man die Klasse nicht kennt, aber Zugriff auf eine Instanz dieser hat (z.B. nach Deserialisierung), kann die Methode GetType() verwendet werden:
String s = "Hallo reflective World"; Type t = s.GetType();
Methoden
Wenn man ein MethodInfo[2]-Objekt hat, kann man damit Methoden aufrufen. Dazu hat die Klasse eine Methode Invoke. Diese erwartet ein Objekt, auf dem die Methode aufgerufen wird und ein Array mit Parametern.
Type t = typeof(String); MethodInfo mi = t.GetMethod("ToUpper"); Object result = mi.Invoke(s, new Object[] { });
result hat als Wert dann
HALLO REFLECTIVE WORLD
Allerdings gibt MethodInfo.Invoke immer ein Object zurück. man muss daher das Ergebnis casten.
Wenn eine Methode keinen Parameter erwartet kann man auch null statt des Arrays übergeben. Das gleiche gilt für statische Methoden, da wird null als erster Parameter übergeben.
Assemblies
Man kann neue Assemblies[3] laden indem man
Assembly a1 = Assembly.Load("Hier Name der Assembly als String angeben"); // oder Assembly a2 = Assembly.LoadFile("Dateiname");
ausführt.
Aus Sicherheitsgründen sollte man, wenn möglich Assemblies nur mit ReflectionLoad* oder in ein andere AppDomain[4] laden.
Wichtige Hinweise
Das Aufzählen der Methoden, Properties und Felder unbekannter Klassen dauert extrem lang. Auch ist es schwer, ein venünftiges Caching dafür zu bauen. Auch wenn eine Methode ToString() für alle Objekte definiert ist kann man nicht die ToString-Methode der Klasse Game auf einem Objekt der Klasse GraphicsDevice aufrufen.
Der Compiler macht das Methoden aufrufen wesentlich besser, er kann diese dann auch optimieren und z.B. inlinen. Bei Verwendung von Reflection ist all das nicht möglich.
Video Tutorial
Auf MSDN gibt es einen Webcast zum Thema[5]
Referenzen
- ↑ http://msdn.microsoft.com/en-us/library/system.type.aspx MSDN-Artikel zur Klasse Type
- ↑ 2,0 2,1 http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.aspx MSDN-Artikel zur Klasse MethodInfo
- ↑ http://msdn.microsoft.com/en-us/library/system.reflection.assembly.aspx MSDN-Artikel zur Klasse Assembly
- ↑ http://msdn.microsoft.com/en-us/library/system.appdomain.aspx MSDN-Artikel zur Klasse AppDomain
- ↑ http://www.microsoft.com/germany/MSDN/webcasts/library.aspx?id=100100298 MSDN Webcast zum Thema Reflection
