Réflexion C#
La réflexion fait référence à la capacité d'un programme à accéder, détecter et modifier son propre état ou comportement.
Les assemblys contiennent des modules, qui contiennent des types, qui contiennent des membres. Reflection fournit des objets qui encapsulent des assemblys, des modules et des types.
Vous pouvez utiliser la réflexion pour créer dynamiquement des instances d'un type, lier un type à un objet existant ou obtenir un type à partir d'un objet existant. Vous pouvez ensuite appeler les méthodes du type ou accéder à ses champs et propriétés.
Avantages et inconvénients
Avantages :
1. La réflexion améliore la flexibilité et l'évolutivité du programme.
2. Réduire le couplage et améliorer les capacités d'adaptation.
3. Il permet au programme de créer et de contrôler des objets de n'importe quelle classe sans coder en dur la classe cible à l'avance.
Inconvénients :
1. Problèmes de performances : L'utilisation de la réflexion est fondamentalement une opération d'interprétation, qui est requise lors de l'accès aux champs et aux méthodes. que le code direct. Par conséquent, le mécanisme de réflexion est principalement utilisé dans les cadres système qui nécessitent une grande flexibilité et évolutivité, et n'est pas recommandé pour les programmes ordinaires.
2. L'utilisation de la réflexion obscurcit la logique interne du programme ; les programmeurs espèrent voir la logique du programme dans le code source, mais la réflexion contourne la technologie du code source, provoquant ainsi une maintenance. Le problème est que le code réflexif est plus complexe que le code direct correspondant.
Utilisations de la réflexion
La réflexion a les utilisations suivantes :
Elle permet de visualiser les informations sur les attributs au moment de l'exécution.
Il permet l'inspection de différents types dans une collection, ainsi que l'instanciation de ces types.
Il permet la liaison paresseuse des méthodes et des propriétés.
Il permet de créer de nouveaux types au moment de l'exécution puis d'utiliser ces types pour effectuer certaines tâches.
Afficher les métadonnées
Nous avons mentionné dans le chapitre ci-dessus que vous pouvez utiliser la réflexion pour afficher les informations sur les attributs. L'objet
MemberInfode la classe System.Reflection doit être initialisé pour découvrir les attributs liés à la classe. Pour ce faire, vous pouvez définir un objet de la classe cible comme suit :
System.Reflection.MemberInfo info = typeof(MyClass);
Le programme suivant le démontre :
using System; [AttributeUsage(AttributeTargets.All)] public class HelpAttribute : System.Attribute { public readonly string Url; public string Topic // Topic 是一个命名(named)参数 { get { return topic; } set { topic = value; } } public HelpAttribute(string url) // url 是一个定位(positional)参数 { this.Url = url; } private string topic; } [HelpAttribute("Information on the class 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.Length; i++) { System.Console.WriteLine(attributes[i]); } Console.ReadKey(); } } }
Lorsque le code ci-dessus est compilé et exécuté, il Les propriétés personnalisées attachées à la classe MyClass sont affichés :
HelpAttribute
Instance
Dans cet exemple nous utiliserons la propriété créée dans le chapitre précédent DeBugInfo et utiliser Reflection pour lire les métadonnées dans la classe Rectangle.
using System; using System.Reflection; namespace BugFixApplication { // 一个自定义属性 BugFix 被赋给类及其成员 [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 = "Return type mismatch")] [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")] class Rectangle { // 成员变量 protected double length; protected double width; public Rectangle(double l, double w) { length = l; width = w; } [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")] public double GetArea() { return length * width; } [DeBugInfo(56, "Zara Ali", "19/10/2012")] public void Display() { Console.WriteLine("Length: {0}", length); Console.WriteLine("Width: {0}", width); Console.WriteLine("Area: {0}", GetArea()); } }//end class Rectangle class ExecuteRectangle { static void Main(string[] args) { Rectangle r = new Rectangle(4.5, 7.5); r.Display(); Type type = typeof(Rectangle); // 遍历 Rectangle 类的属性 foreach (Object attributes in type.GetCustomAttributes(false)) { DeBugInfo dbi = (DeBugInfo)attributes; if (null != dbi) { Console.WriteLine("Bug no: {0}", dbi.BugNo); Console.WriteLine("Developer: {0}", dbi.Developer); Console.WriteLine("Last Reviewed: {0}", dbi.LastReview); Console.WriteLine("Remarks: {0}", dbi.Message); } } // 遍历方法属性 foreach (MethodInfo m in type.GetMethods()) { foreach (Attribute a in m.GetCustomAttributes(true)) { DeBugInfo dbi = (DeBugInfo)a; if (null != dbi) { Console.WriteLine("Bug no: {0}, for Method: {1}", dbi.BugNo, m.Name); Console.WriteLine("Developer: {0}", dbi.Developer); Console.WriteLine("Last Reviewed: {0}", dbi.LastReview); Console.WriteLine("Remarks: {0}", dbi.Message); } } } Console.ReadLine(); } } }
Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants :
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: