Attribute und Reflection
Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy. Lektion 44 von 70.
Attribute sind Metadaten-Tags, die du an Codeelemente wie Klassen, methods oder Eigenschaften anhängst. Sie ändern nicht direkt, wie der Code ausgeführt wird, sondern stellen Informationen bereit, die zur Laufzeit gelesen werden können. Reflexion ist der Mechanismus, der diese Metadaten liest.
Du wendest ein Attribut an, indem du es in eckigen Klammern über dem Zielelement platzierst:
[Obsolete("Use NewMethod instead")]
public void OldMethod() { }
[Serializable]
public class Person
{
public string Name { get; set; }
}Du kannst benutzerdefinierte Attribute erstellen, indem du von Attribute erbst:
public class AuthorAttribute : Attribute
{
public string Name { get; }
public AuthorAttribute(string name) => Name = name;
}
[Author("John")]
public class Calculator { }Mit Reflection kannst du Typen untersuchen und zur Laufzeit mithilfe des Namespace System.Reflection Attribute auslesen:
Type type = typeof(Calculator);
var attr = type.GetCustomAttribute<AuthorAttribute>();
Console.WriteLine(attr.Name); // JohnDu kannst auch methods und Eigenschaften entdecken und sie dynamisch aufrufen:
MethodInfo[] methods = type.GetMethods();
foreach (var method in methods)
Console.WriteLine(method.Name);Attribute und Reflection bilden die Grundlage vieler Frameworks – Serialisierungsbibliotheken verwenden sie, um die JSON-Ausgabe zu steuern, Test-Frameworks nutzen sie, um Testmethoden zu erkennen, und Dependency-Injection-Container setzen sie ein, um Dienste automatisch zu verbinden.
Aufgabe
EinfachErstellen wir ein Plugin-Erkennungssystem, das benutzerdefinierte Attribute und Reflection verwendet, um Klassen, die als Plugins gekennzeichnet sind, automatisch zu finden und zu beschreiben. Dies ähnelt der Funktionsweise echter Frameworks, die Komponenten, Testmethoden oder API-Endpunkte zur Laufzeit erkennen.
Du organisierst deinen Code auf drei Dateien verteilt:
PluginAttribute.cs: Erstelle ein benutzerdefiniertes Attribut namensPluginAttributeim NamespacePluginSystem. Dein Attribut sollte:- Von
Attributeerben - Zwei schreibgeschützte Eigenschaften besitzen:
Name(string) undVersion(string) - Beide Werte über seinen Konstruktor akzeptieren
- Von
Plugins.cs: Erstelle mehrere Plugin-Klassen im NamespacePluginSystem. Einige sollten mit deinemPluginAttributedekoriert sein, eine jedoch nicht:ImageProcessor– gekennzeichnet mit[Plugin("Image Processor", "1.0")]DataExporter– gekennzeichnet mit[Plugin("Data Exporter", "2.5")]HelperUtility– NICHT mit einem Attribut gekennzeichnet (dies ist einfach eine reguläre Klasse)
Program.cs: Verwende in deiner Hauptdatei Reflection, um alle Klassen zu erkennen, die über dasPluginAttributeverfügen. Gib für jedes erkannte Plugin seine Informationen aus. Dazu musst du:- Alle Typen aus der aktuellen Assembly abrufen
- Jeden Typ auf das
PluginAttributeüberprüfen - Die Eigenschaften
NameundVersiondes Attributs auslesen und anzeigen
Verwende System.Reflection, um Typen zu untersuchen und benutzerdefinierte Attribute abzurufen. Die Methode GetCustomAttribute<T>() gibt null zurück, wenn das Attribut nicht vorhanden ist. Du kannst dies daher verwenden, um zu filtern, welche Klassen tatsächlich Plugins sind.
Gib jedes erkannte Plugin in diesem Format aus, eines pro Zeile:
Plugin: {Name} (v{Version})Die Plugins sollten in dieser Reihenfolge ausgegeben werden: zuerst ImageProcessor, dann DataExporter. Die Klasse HelperUtility sollte in der Ausgabe nicht erscheinen, da ihr das Attribut fehlt.
Erwartete Ausgabe:
Plugin: Image Processor (v1.0)
Plugin: Data Exporter (v2.5)Diese Aufgabe veranschaulicht, wie Frameworks Attribute als Markierungen und Reflection verwenden, um sie zu erkennen – dieselbe Technik bildet die Grundlage für Dependency-Injection-Container, Serialisierungsbibliotheken und Test-Frameworks!
Probier es selbst
using System;
using System.Reflection;
using PluginSystem;
class Program
{
public static void Main(string[] args)
{
// TODO: Hole alle Typen aus der aktuellen Assembly
// Hinweis: Verwende Assembly.GetExecutingAssembly().GetTypes()
// TODO: Gehe durch jeden Typ und prüfe, ob er das PluginAttribute hat
// Hinweis: Verwende type.GetCustomAttribute<PluginAttribute>()
// TODO: Wenn das Attribut existiert, gib die Plugin-Info im Format aus:
// Plugin: {Name} (v{Version})
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienNamespaces & DirektivenEinführung in Klassen & ObjekteDas 'this'-SchlüsselwortMethoden und ParameterFelder vs. EigenschaftenKonstruktorenObjektinitialisiererWiederholung – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbungs-(:)-SyntaxDas „base“-Schlüsselwort„virtual“- und „override“-SchlüsselwörterVersiegelte KlassenDie „object“-BasisklasseWiederholung – Mitarbeiterhierarchie7Erweiterte Funktionen
Überladen von OperatorenIndexer (this[])ToString()-ÜberschreibungErweiterungsmethodenRückblick – Benutzerdefinierte Liste10Entwurfsmuster Teil 1
Einführung in EntwurfsmusterThread-sicheres SingletonFactory-MusterObserver-Muster (Events)Strategy-Muster13Abschließende Herausforderungen
E-Learning-PlattformKomponente für SpielfigurenFahrzeugvermietungsdienst2Eigenschaften & statische Member
Automatisch implementierte EigenschaftenNur lesbare/schreibbare EigenschaftenStatische Felder & MethodenStatische KlassenMember mit Ausdruckskörpern5Polymorphie & Interfaces
Compile- vs. Laufzeit-PolymorphieInterface vs. abstrakte KlasseMehrere InterfacesExplizite InterfacesUpcasting & DowncastingWiederholung – Formenrechner8Fortgeschrittene OOP-Konzepte
Komposition statt VererbungGenerics (Klassen & Methoden)Delegates und EventsAttribute und ReflectionIDisposable & using-AnweisungGrundlagen der Dependency Injection3Klassenarchitektur
Instanz- vs. statische DatenSchlüsselwörter 'readonly' & 'const'Backing FieldsRückblick – Bankkontenverwaltung6Kapselung
ZugriffsmodifikatorenEigenschaften zur KapselungImplementierung der DatenkapselungMuster für UnveränderlichkeitRückblick – SchülerdatenÜbe selbstständig: Online-C#-Compiler