Home > Backend Development > C#.Net Tutorial > Examples of the best combination of reflection and dynamic in C#

Examples of the best combination of reflection and dynamic in C#

黄舟
Release: 2017-09-07 13:32:47
Original
1603 people have browsed it

This article mainly introduces the sample code of the best combination of reflection and dynamic in C#. Friends who need it can refer to it

Reflection technology is widely used in C#. As for what reflection is... ..If you don’t understand, please read the explanation in the next paragraph, otherwise please skip the next paragraph. Advertisement: Friends who like my articles, please pay attention to my blog, which will also help improve my motivation for writing.

Reflection: When you have your back to a beautiful woman or handsome guy but cannot turn around to observe and study it carefully (purely fictitious, any coincidence or similarity), a small mirror can meet your needs. In the process of C# programming, we often encounter a similar situation: there is a dll class library written by others that you want to use but there is no program documentation... At this time, through the functions provided by C# Runtime, you can use the dll class library Load the library into your program and study every part of the dll. This is reflection in C#.

Personally think that the most prominent advantage or rationality of reflection is: dynamic adjustment of program functions (Runtime dynamic object creation) without modifying the original code of the program.

Example:


 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();
  }
 }
Copy after login

If the above Run function is not necessarily executed by Person, sometimes it needs to be Car and sometimes it needs Person. A common solution is to add a judgment structure such as if, as follows:


 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();
  }
Copy after login

This structure does solve the current needs, but it is not robust. With the increase in IRun interface implementation and inheritance of related classes, the above judgment structure will also grow rapidly. One of the major principles followed by object-oriented programming and design patterns is to encapsulate transformations, so the above program cannot cope with changes well. We do not involve the knowledge of "design patterns" here, so the sample code below is only to simplify the above program and does not deliberately apply the knowledge related to design patterns. As follows:


 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();
  }
Copy after login

After the above modification, the program can create an instance of IRun through Activator.CreateInstance based on the user's input. The program will no longer be implemented with IRun. Changes will occur as the impact of this problem increases. The above advantages are obtained through reflection, which is what I think is the "reasonableness of the existence of reflection".

Activator and Assembly implement reflection method to create objects

In C#, objects can be created through reflection method through Activator.CreateInstance (static) and Assembly.CreateInstance (non-static), in which Assembly.CreateInstance still calls Activator.CreateInstance internally.

Depending on whether the type object to be dynamically created is in the current assembly, reflection-created objects can be divided into: creating type objects within the assembly and creating type objects outside the assembly.

Create a type object within the 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());
  }
Copy after login

Create a type object outside the assembly

Add a class library (another assembly) to the project, as shown below:

Add a Boss class, as shown below:


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;
  }
 }
}
Copy after login

Before obtaining a Boss object, first add a reference to Lib. The acquisition example is as follows:


 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());
  }
Copy after login

About how the CLR finds and locates objects during reflection For the loaded assembly, please refer to MSDN for knowledge about reflection.

Reflection access fields and call methods (properties)

In addition to helping us dynamically create objects, reflection can also help us dynamically access the object's methods (properties) or Field, the specific method will be changed or expanded due to different C# versions. Please refer to MSDN for more in-depth content. The following is just a simple example (standard usage).

Change the name of the boss, example: ​


 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());
  }
Copy after login

Output:

Let the boss pay:


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:老大你真棒!");
  }
Copy after login

Output:

##The combination of dynamic and reflection

Because reflection is a runtime type operation, we face the problem of type uncertainty when programming. According to the previous article "C# Anonymous Object (Anonymous Type), Var, Dynamic Type Dynamic", the dynamic dynamic type combined with the reflection program we wrote can greatly optimize the program logic (access to code restricted by the protection level is not within this scope).

Optimization of the above code:


private static void ReflectionBoss1()
  {
   string classPath ="Lib.Boss";
   var handler = Activator.CreateInstance("Lib", classPath);
   dynamic b = handler.Unwrap();
   Console.WriteLine(b.Talk());
  }
  private static void ReflectionBoss2()
  {
   string classPath ="Lib.Boss";
   var assembly = Assembly.Load("Lib");
   dynamic b = assembly.CreateInstance(classPath);
   Console.WriteLine(b.Talk());
  }
Copy after login
Call reflection through dynamic dynamic type object b to get the properties and methods of the object that can be called directly, thus eliminating the need for Frequent type conversion operations.

Common application scenarios of reflection

Application scenario What impressed me most was the MS Petshop example. When switching from SQL Server database to Oracle database, reflection obtains different data access layers. However, I have never encountered the situation of switching databases midway in actual projects. Other application scenarios are basically similar to the above examples. If you find more application scenarios, please add 3ks.

Advantages and disadvantages of reflection

Advantages: Reflection makes the program more flexible

Disadvantages: Reflection runs relatively slowly

As for Reflection is slower than ordinary programs. I have not tested it and do not plan to test it. The reality is: Ms advocates the use of dynamic, Mvc is popular, Ms continuously optimizes CLR, and improves machine performance, so you don’t need to consider too much reflection performance issues during development. If there is a bottleneck in the running speed of the program you write (you should first ensure that your program is written reasonably), I think it is more practical to study database optimization, data caching, web caching, load balancing and other technologies.

The above is the detailed content of Examples of the best combination of reflection and dynamic in C#. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template