So greifen Sie mit Reflection auf interne Klassen zu

74

Wie kann ich auf eine interne Klasse einer Assembly zugreifen? Angenommen, ich möchte auf System.ComponentModel.Design.DesignerHost zugreifen. Hier ist der DesignerHost eine interne und versiegelte Klasse.

Wie kann ich einen Code schreiben, um die Assembly und den Typ zu laden?

Dattebayo
quelle

Antworten:

114

Im Allgemeinen sollten Sie dies nicht tun. Wenn ein Typ als intern markiert wurde, bedeutet dies, dass Sie ihn nicht von außerhalb der Assembly verwenden dürfen. Es könnte in einer späteren Version entfernt, geändert usw. werden.

Allerdings Reflexion macht Sie auf Zugriffstypen und Mitgliedern ermöglichen , die nicht öffentlich sind - nur Blick für Überlastungen , die einen nehmen BindingFlagsArgument, und umfassen BindingFlags.NonPublicin den Flags , dass Sie weitergeben.

Wenn Sie den vollständig qualifizierten Namen des Typs (einschließlich der Assembly-Informationen) haben, Type.GetType(string)sollte nur der Aufruf funktionieren. Wenn Sie die Assembly im Voraus kennen und einen öffentlichen Typ innerhalb dieser Assembly kennen, ist die Verwendung typeof(TheOtherType).Assemblyzum Abrufen der Assemblyreferenz im Allgemeinen einfacher. Sie können dann aufrufen Assembly.GetType(string).

Jon Skeet
quelle
10
@dattebayo: Nur um Jons Antwort zu vervollständigen, beachten Sie, dass Ihr Code in vollem Vertrauen ausgeführt werden muss, sonst schlägt die Reflexion über nicht öffentliche Mitglieder fehl
Thomas Levesque
3
Manchmal muss man einfach, bis es kaputt geht. Ich habe einen WPF- DataGridBefehl, dessen Parameter ist SelectedItems. Im Befehl wird der Parameter objectnur vom Typ empfangen SelectedCellCollection, auf den in meinem Code nicht zugegriffen werden kann. Ich brauche diese Art von Cheat in der Hoffnung, den objectParameter auf a zu setzen SelectedCellCollection.
ProfK
15

So laden Sie die Baugruppe und den Typ, den Sie in Ihrem Beispiel angegeben haben:

Assembly design = Assembly.LoadFile(@"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Design.dll");
Type designHost = design.GetType("System.ComponentModel.Design.DesignerHost");
Patrick McDonald
quelle
11
Sie können nurAssembly.Load("System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
abatishchev
6
Wenn Sie nur einen Typ benötigen, können Sie das explizite Laden der Baugruppe überspringen:var designHost = Type.GetType("System.ComponentModel.Design.DesignerHost, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
Max Truxa