Maison >développement back-end >Tutoriel C#.Net >Exemples de la meilleure combinaison de réflexion et de dynamique en C#

Exemples de la meilleure combinaison de réflexion et de dynamique en C#

黄舟
黄舟original
2017-09-07 13:32:471600parcourir

Cet article présente principalement l'exemple de code de la meilleure combinaison de réflexion et de dynamique en C#. Les amis qui en ont besoin peuvent s'y référer

La technologie de réflexion est largement utilisée en C#. ..Si vous ne comprenez pas, veuillez lire l’explication dans le paragraphe suivant, sinon veuillez sauter le paragraphe suivant. Publicité : Amis qui aiment mes articles, faites attention à mon blog, ce qui contribuera également à améliorer ma motivation à écrire.

Réflexion : lorsque vous tournez le dos à une belle femme ou à un beau mec mais que vous ne pouvez pas vous retourner pour l'observer et l'étudier attentivement (c'est purement fictif, toute coïncidence ou similitude), un petit miroir peut répondre à votre besoins. Dans le processus de programmation C#, nous rencontrons souvent une situation similaire : il existe une bibliothèque de classes dll écrite par d'autres que vous souhaitez utiliser mais il n'y a pas de documentation sur le programme... À l'heure actuelle, grâce aux fonctions fournies par C# Runtime, vous peut utiliser la bibliothèque de classes DLL Chargez la bibliothèque dans votre programme et étudiez chaque partie de la DLL. C'est une réflexion en C#.

Personnellement, je pense que l'avantage ou la rationalité le plus marquant de la réflexion est : l'ajustement dynamique des fonctions du programme (création d'objet dynamique au Runtime) sans modifier le code original du programme

Exemple :


 interface IRun {
  void Run();
 }
 class Person : IRun
 {
  public void Run()
  {
   Console.WriteLine("走,去LOL啊!");
  }
 }
 class Car : IRun
 {
  public void Run()
  {
   Console.WriteLine("呜...........");
  }
 }
 class Program
 {
  static void Main(string[] args)
  {
   IRun e = new Person();
   e.Run();
   Console.ReadLine();
  }
 }
Si la fonction Run ci-dessus n'est pas nécessairement exécutée par Person, parfois elle doit être Car et parfois elle a besoin de Person. Une solution courante consiste à ajouter des structures de jugement telles que if, comme suit :


 static void Main(string[] args)
  {
   Console.WriteLine("请输入:Car或Person");
   string type = Console.ReadLine();
   IRun e = null;
   if ("Car" == type)
   {
    e = new Car();
   }else if("Person" == type)
   {
    e = new Person();
   }
   if(null != e)
    e.Run();
   Console.ReadLine();
  }
Cette structure résout les besoins actuels, mais elle n'est pas robuste. Avec l'augmentation de l'implémentation de l'interface IRun et de l'héritage des classes associées, la structure de jugement ci-dessus se développera également rapidement. L'un des principes majeurs suivis par la programmation orientée objet et les modèles de conception est d'encapsuler les transformations, de sorte que le programme ci-dessus ne peut pas bien gérer les changements. Nous n'impliquons pas ici la connaissance des "modèles de conception", donc l'exemple de code ci-dessous vise uniquement à simplifier le programme ci-dessus et n'applique pas délibérément les connaissances liées aux modèles de conception. Comme suit :


 static void Main(string[] args)
  {
   Console.WriteLine("请输入:Car或Person");
   string type = Console.ReadLine();
   string classPath = String.Format("namespace.{0}", type);
   IRun e = Activator.CreateInstance(null, classPath).Unwrap() as IRun;

   if(null != e)
    e.Run();
   Console.ReadLine();
  }
Après la modification ci-dessus, le programme peut créer une instance de IRun via Activator.CreateInstance en fonction de la saisie de l'utilisateur. Le programme n'inclura plus. IRun ici Les changements se produisent à mesure que le nombre de responsables de la mise en œuvre augmente en raison de l'impact de ce problème. Les avantages ci-dessus sont obtenus grâce à la réflexion, ce que je considère comme le « caractère raisonnable de l'existence de la réflexion ».

Activator et Assembly implémentent la réflexion pour créer des objets

La création d'objets en C# via la réflexion peut être effectuée via Activator.CreateInstance (statique) et Assembly .CreateInstance (non statique), dans lequel Assembly.CreateInstance appelle toujours Activator.CreateInstance en interne.

Selon que l'objet type à créer dynamiquement se trouve dans l'assemblage actuel, les objets créés par réflexion peuvent être divisés en : création d'objets type au sein de l'assemblage et création d'objets type en dehors de l'assemblage.

Créer un objet de type au sein de l'assembly


  private static void ReflectionIRun1(string className)
  {
   string classPath = String.Format("namespace.{0}", className);
   //参数 null ,指出所要创建类型对象位于当前程序集 
   var handler = Activator.CreateInstance(null, classPath);
   IRun e = (IRun)handler.Unwrap();
   Console.WriteLine(e.Run());
  }
  private static void ReflectionIRun2(string className)
  {
   string classPath = String.Format("namespace.{0}", className);
   //typeof(IRun).Assembly 获取 IRun 类型所在的程序集
   object obj = typeof(IRun).Assembly.CreateInstance(null, classPath);
   IRun e = (IRun)obj;
   Console.WriteLine(e.Run());
  }

Créer un objet de type en dehors de l'assembly

Ajoutez une bibliothèque de classes (un autre assembly) au projet, comme indiqué ci-dessous :

Ajoutez une classe Boss, comme indiqué ci-dessous :


namespace Lib
{
 public class Boss
 {
  private string name = "老大";
  
  public string Name{
   get {return name;}
  }
  public string Talk()
  {
   return "你们都被开除了......";
  }
  //老板不会算账,总是多付钱,所以很有自知之明的将Payfor设为private,防止外部人员调用
  private int Payfor(int total)
  {
   return total + 10;
  }
 }
}
Avant d'obtenir un objet Boss, ajoutez d'abord une référence à Lib. L'exemple d'acquisition est le suivant :


 private static void ReflectionBoss1()
  {
   string classPath ="Lib.Boss";
   //"Lib" 参数指明要加载的程序集(即要创建的对象类型在哪个程序集中定义)
   var handler = Activator.CreateInstance("Lib", classPath);
   Boss b = handler.Unwrap() as Boss;
   Console.WriteLine(b.Talk());
  }
  private static void ReflectionBoss2()
  {
   string classPath ="Lib.Boss";
   //Assembly.Load("Lib") 加载的程序集(即要创建的对象类型在哪个程序集中定义)
   var assembly = Assembly.Load("Lib");
   Boss b = (Boss)assembly.CreateInstance(classPath);
   Console.WriteLine(b.Talk());
  }
À propos de la réflexion Comment le CLR trouve et localise l'assembly à charger, veuillez vous référer à MSDN pour en savoir plus sur la réflexion.

Champs d'accès à la réflexion et méthodes d'appel (propriétés)

En plus de nous aider à créer dynamiquement des objets, la réflexion peut également nous aider à accéder dynamiquement aux méthodes (propriétés) d'objets ou Champ, la méthode spécifique sera modifiée ou étendue en raison des différentes versions de C#. Veuillez vous référer à MSDN pour un contenu plus détaillé. Ce qui suit n'est qu'un exemple simple (usage standard).

Renommer le patron, exemple :                                                                                                                                                                 Argent :


 private static void ReflectionBoss1()
  {
   string classPath = "Lib.Boss";
   //"Lib" 参数指明要加载的程序集(即要创建的对象类型在哪个程序集中定义)
   var handler = Activator.CreateInstance("Lib", classPath);
   Boss b = handler.Unwrap() as Boss;
   //关键代码
   FieldInfo f = b.GetType().GetField("name", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
   f.SetValue(b, "小二");
   Console.WriteLine("{0}:{1}", b.Name, b.Talk());
  }
Résultat :

dynamique et réflexion combinées


Parce que la réflexion est une opération de type au moment de l'exécution, elle est confrontée au problème de l'incertitude de type lors de la programmation. Selon l'article précédent "C# Anonymous Object (Anonymous Type), Var, Dynamic Type Dynamic", le type dynamique dynamique combiné au programme de réflexion que nous avons écrit peut grandement optimiser la logique du programme (l'accès au code restreint par le niveau de protection n'est pas dans ce périmètre).

private static void ReflectionBoss1()
  {
   string classPath = "Lib.Boss";
   //"Lib" 参数指明要加载的程序集(即要创建的对象类型在哪个程序集中定义)
   var handler = Activator.CreateInstance("Lib", classPath);
   Boss b = handler.Unwrap() as Boss;
   //关键代码
   MethodInfo method = b.GetType().GetMethod("Payfor", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance);
   object money = method.Invoke(b, new object[] { 10 });
   Console.WriteLine("DW039:老大给我报销10元钱车费......");
   Console.WriteLine("{0}:.....,算不清了,给你这些吧。",b.Name);
   Console.WriteLine("DW039:......");
   Console.WriteLine("{0}:{1}", b.Name,money);
   Console.WriteLine("DW039:老大你真棒!");
  }
Optimisation du code ci-dessus :

Grâce à l'objet de type dynamique dynamique b pour appeler la réflexion, les propriétés et méthodes de l'objet peuvent être appelées directement, économisant ainsi Aller aux opérations fréquentes de conversion de type.

Scénarios d'application courants de réflexion

Le scénario d'application qui m'a le plus impressionné était l'exemple de MS Petshop Lors du passage d'une base de données SQL Server à une base de données Oracle, la réflexion obtient différentes couches d'accès aux données. Cependant, je n'ai jamais rencontré de situation de changement de base de données à mi-chemin dans des projets réels. D'autres scénarios d'application sont fondamentalement similaires aux exemples ci-dessus. Si vous trouvez plus de scénarios d'application, veuillez ajouter 3ks.

Avantages et inconvénients de la réflexion

Avantages : La réflexion rend le programme plus flexible

Inconvénients : La réflexion s'exécute relativement lentement

Comme car Reflection est plus lent que les programmes ordinaires, je ne l'ai pas testé et je n'ai pas l'intention de le tester. La réalité est la suivante : Ms préconise l'utilisation de la dynamique, Mvc est populaire, Ms optimise continuellement le CLR et améliore les performances de la machine, vous n'avez donc pas besoin de trop prendre en compte les problèmes de performances de réflexion pendant le développement. S'il y a un goulot d'étranglement dans la vitesse d'exécution du programme que vous écrivez (vous devez d'abord vous assurer que votre programme est écrit de manière raisonnable), je pense qu'il est plus pratique d'étudier l'optimisation des bases de données, la mise en cache des données, la mise en cache Web, l'équilibrage de charge et d'autres technologies.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn