C# Réflexion
La réflexion désigne la capacité d’un programme à accéder à son propre état ou comportement, à l’inspecter et à le modifier.
Les assemblys contiennent des modules, les modules contiennent des types, et les types contiennent des membres. La réflexion fournit des objets qui encapsulent les assemblys, les modules et les types.
Vous pouvez utiliser la réflexion pour créer dynamiquement une instance d’un type, lier le type à un objet existant, ou obtenir le type à partir d’un objet existant. Ensuite, vous pouvez 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’extensibilité des programmes.
- 2. Elle réduit le couplage et améliore l’auto-adaptabilité.
- 3. Elle permet aux programmes 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 performance : l’utilisation de la réflexion est essentiellement une opération d’interprétation, qui est beaucoup plus lente que le code direct lors de l’accès aux champs et aux méthodes. Par conséquent, la réflexion est principalement utilisée dans les frameworks système qui exigent une grande flexibilité et extensibilité ; elle n’est pas recommandée pour les programmes ordinaires.
- 2. L’utilisation de la réflexion masque la logique interne des programmes ; les programmeurs s’attendent à voir la logique du programme dans le code source, mais la réflexion contourne les techniques du code source, ce qui cause des problèmes de maintenance. Le code de réflexion est plus complexe que le code direct équivalent.
Objectif de la réflexion
La réflexion a les utilisations suivantes :
- Elle permet de consulter les informations d'attribut au moment de l'exécution.
- Elle permet d'examiner les différents types d'un assembly et d'instancier ces types.
- Elle permet la liaison tardive des méthodes et des propriétés.
- Elle 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
Comme nous l'avons mentionné dans les chapitres précédents, la réflexion peut être utilisée pour afficher les informations d'attribut.
System.ReflectionClasseMemberInfoUn objet doit être initialisé afin de découvrir les attributs associé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 :
Exemple
[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute
{
public readonly string Url;
public string Topic // Topic est un paramètre nommé
{
get
{
return topic;
}
set
{
topic = value;
}
}
public HelpAttribute(string url) // url est un paramètre de positionnement (positionnel)
{
this.Url = url;
}
private string topic;
}
[HelpAttribute("Informations sur la classe 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.Longueur; i++)
{
System.Console.WriteLine(attributes[i]);
}
Console.ReadKey();
}
}
}
Lorsque le code ci-dessus est compilé et exécuté, il affichera les attributs attachés à la classeMyClassLes attributs personnalisés sur :
HelpAttribute
Exemple
Dans cet exemple, nous utiliserons ce qui a été créé dans le chapitre précédent.DeBugInfoattributs, et utiliser la réflexion pour les lireRectangleMétadonnées dans la classe.
Exemple
using System.Reflection;
namespace BugFixApplication
{
// aCustomFeatures BugFix par赋Giveclass et son membre
[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 = "Variable inutilisée")]
class Rectangle
{
// Variables membres
protected double length;
protected double width;
public Rectangle(double l, double w)
{
longueur = 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());
}
}//fin de la classe Rectangle
class ExecuteRectangle
{
static void Main(string[] args)
{
Rectangle r = new Rectangle(4.5, 7.5);
r.Afficher();
Type type = typeof(Rectangle);
// Parcourir les attributs de la classe Rectangle
foreach (Object attributes in type.GetCustomAttributes(false))
{
DeBugInfo dbi = (DeBugInfo)attributes;
if (null != dbi)
{
Console.WriteLine("N° de bug : {0}", dbi.BugNo);
Console.WriteLine("Développeur : {0}", dbi.Developer);
Console.WriteLine("Dernière révision: {0}",
dbi.LastReview);
Console.WriteLine("Remarques: {0}", dbi.Message);
}
}
// Fonctionnalités de la méthode d'itération
foreach (MethodInfo m in type.GetMethods())
{
foreach (Attribute a in m.GetCustomAttributes(true))
{
DeBugInfo dbi = (DeBugInfo)a;
if (null != dbi)
{
Console.WriteLine("N° de bug: {0}, pour la méthode: {1}",
dbi.BugNo, m.Name);
Console.WriteLine("Développeur : {0}", dbi.Developer);
Console.WriteLine("Dernière révision: {0}",
dbi.LastReview);
Console.WriteLine("Remarques: {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:autres extensions