C# Reflexion

Reflexion bezeichnet die Fähigkeit eines Programms, auf seinen eigenen Zustand oder sein eigenes Verhalten zuzugreifen, ihn zu untersuchen und ihn zu ändern.

Assemblys enthalten Module, Module enthalten Typen und Typen enthalten Member. Die Reflexion stellt Objekte bereit, die Assemblys, Module und Typen kapseln.

Sie können die Reflexion verwenden, um dynamisch eine Instanz eines Typs zu erstellen, den Typ an ein vorhandenes Objekt zu binden oder den Typ von einem vorhandenen Objekt abzurufen. Danach können Sie die Methoden des Typs aufrufen oder auf dessen Felder und Eigenschaften zugreifen.

Vorteile und Nachteile

Vorteile:

  • 1. Reflexion verbessert die Flexibilität und Erweiterbarkeit von Programmen.
  • 2. Sie reduziert die Kopplung und verbessert die Selbstanpassungsfähigkeit.
  • 3. Sie ermöglicht Programmen, Objekte beliebiger Klassen zu erstellen und zu steuern, ohne die Zielklasse im Voraus fest zu codieren.

Nachteile:

  • 1. Leistungsprobleme: Die Verwendung von Reflexion ist im Wesentlichen ein interpretativer Vorgang, der beim Zugriff auf Felder und Methoden viel langsamer als direkter Code ist. Daher wird Reflexion hauptsächlich in Systemframeworks verwendet, die hohe Flexibilität und Erweiterbarkeit erfordern; für gewöhnliche Programme wird sie nicht empfohlen.
  • 2. Die Verwendung von Reflexion verschleiert die interne Logik von Programmen; Programmierer erwarten, die Programmlogik im Quellcode zu sehen, aber Reflexion umgeht Quellcode-Techniken und verursacht dadurch Wartungsprobleme. Reflexionscode ist komplexer als entsprechender direkter Code.

Zweck der Reflexion

Reflexion hat die folgenden Verwendungszwecke:

  • Sie ermöglicht es Ihnen, Attributinformationen zur Laufzeit anzuzeigen.
  • Sie ermöglicht es Ihnen, die verschiedenen Typen in einer Assembly zu untersuchen und diese Typen zu instanziieren.
  • Sie ermöglicht die späte Bindung von Methoden und Eigenschaften.
  • Sie ermöglicht es Ihnen, zur Laufzeit neue Typen zu erstellen und diese Typen dann zu verwenden, um einige Aufgaben auszuführen.

Metadaten anzeigen

Wie in den vorherigen Kapiteln erwähnt, kann Reflexion verwendet werden, um Attributinformationen anzuzeigen.

System.ReflectionClassMemberInfoEin Objekt muss initialisiert werden, um die der Klasse zugeordneten Attribute zu ermitteln. Dazu können Sie ein Objekt der Zielklasse definieren, wie folgt:

System.Reflection.MemberInfo info = typeof(MyClass);

Das folgende Programm demonstriert dies:

Beispiel

using System;

[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute
{
   public readonly string Url;

   public string Topic  // Topic ist ein benannter Parameter
   {
      get
      {
         return topic;
      }
      set
      {

         topic = value;
      }
   }

   public HelpAttribute(string url)  // url ist ein Positionsparameter(positionaler Parameter)
   {
      this.Url = url;
   }

   private string topic;
}
[HelpAttribute("Informationen über die Klasse MyClass")]
class MyClass
{
}

namespace AttributeAppl
{
   class Program
   {
      static void Main(string[] args)
      {
         System.Reflection.MemberInfo info = typeof(MyClass);
         object[] attributes = info.GetCustomAttributes(true);
         for (int i = 0; i < attributes.Länge; i++)
         {
            System.Console.WriteLine(attributes[i]);
         }
         Console.ReadKey();

      }
   }
}

Wenn der obige Code kompiliert und ausgeführt wird, werden die Attribute angezeigt, die an die KlasseMyClassangehängt sind. Die benutzerdefinierten Attribute für:

HelpAttribute

Beispiel

In diesem Beispiel verwenden wir das, was im vorherigen Kapitel erstellt wurde.DeBugInfoAttribute und verwenden Reflexion, um sie zu lesenRectangleMetadaten in der Klasse.

Beispiel

using System;
using System.Reflection;
namespace BugFixApplication
{
   // aCustomFeatures BugFix By赋Giveclass anditsmember
   [AttributeUsage(AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

   public class DeBugInfo : System.Attribute
   {
      private int bugNo;
      private string developer;
      private string lastReview;
      public string message;

      public DeBugInfo(int bg, string dev, string d)
      {
         this.bugNo = bg;
         this.developer = dev;
         this.lastReview = d;
      }

      public int BugNo
      {
         get
         {
            return bugNo;
         }
      }
      public string Developer
      {
         get
         {
            return developer;
         }
      }
      public string LastReview
      {
         get
         {
            return lastReview;
         }
      }
      public string Message
      {
         get
         {
            return message;
         }
         set
         {
            message = value;
         }
      }
   }
   [DeBugInfo(45, "Zara Ali", "12/8/2012",
        Message = "Rückgabetyp stimmt nicht überein")]
   [DeBugInfo(49, "Nuha Ali", "10/10/2012",
        Message = "Unbenutzte Variable")]
   class Rectangle
   {
      // Membervariablen
      protected double length;
      protected double width;
      public Rectangle(double l, double w)
      {
         length = l;
         width = w;
      }
      [DeBugInfo(55, "Zara Ali", "19/10/2012",
           Message = "Rückgabetyp stimmt nicht überein")]
      public double GetArea()
      {
         return length * width;
      }
      [DeBugInfo(56, "Zara Ali", "19/10/2012")]
      public void Display()
      {
         Console.WriteLine("Länge: {0}", length);
         Console.WriteLine("Breite: {0}", width);
         Console.WriteLine("Fläche: {0}", GetArea());
      }
   }//Ende der Klasse Rectangle  
   
   class ExecuteRectangle
   {
      static void Main(string[] args)
      {
         Rectangle r = new Rectangle(4.5, 7.5);
         r.Anzeigen();
         Type type = typeof(Rectangle);
         // Durchlaufe die Attribute der Rectangle-Klasse
         foreach (Object attributes in type.GetCustomAttributes(false))
         {
            DeBugInfo dbi = (DeBugInfo)attributes;
            if (null != dbi)
            {
               Console.WriteLine("Fehlernummer: {0}", dbi.BugNo);
               Console.WriteLine("Entwickler: {0}", dbi.Developer);
               Console.WriteLine("Zuletzt überprüft: {0}",
                                        dbi.LastReview);
               Console.WriteLine("Bemerkungen: {0}", dbi.Message);
            }
         }
         
         // Merkmale der Iterationsmethode
         foreach (MethodInfo m in type.GetMethods())
         {
            foreach (Attribute a in m.GetCustomAttributes(true))
            {
               DeBugInfo dbi = (DeBugInfo)a;
               if (null != dbi)
               {
                  Console.WriteLine("Fehler-Nr.: {0}, für Methode: {1}",
                                                dbi.BugNo, m.Name);
                  Console.WriteLine("Entwickler: {0}", dbi.Developer);
                  Console.WriteLine("Zuletzt überprüft: {0}",
                                                dbi.LastReview);
                  Console.WriteLine("Bemerkungen: {0}", dbi.Message);
               }
            }
         }
         Console.ReadLine();
      }
   }
}

Wenn der obige Code kompiliert und ausgeführt wird, liefert er die folgenden Ergebnisse:

Length: 4.5
Width: 7.5
Area: 33.75
Bug No: 49
Developer: Nuha Ali
Last Reviewed: 10/10/2012
Remarks: Unused variable
Bug No: 45
Developer: Zara Ali
Last Reviewed: 12/8/2012
Remarks: Return type mismatch
Bug No: 55, for Method: GetArea
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: Return type mismatch
Bug No: 56, for Method: Display
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: 
Weitere Erweiterungen