關於C#反射概念,附帶案例!

2023-12-13 18:00:36

反射

C#中的反射是一種使程式在執行時能夠動態地獲取型別資訊並呼叫其成員的技術。通過反射,程式可以在執行時進行型別的動態載入、建立物件、呼叫方法和屬性,以及存取和修改欄位等。反射可以使程式更加靈活,但也增加了一定的效能開銷。

在C#中,反射主要是通過System.Reflection名稱空間中的類來實現的。以下是一些常用的反射類和方法:

  1. Type類:Type類表示一個型別,可以通過其靜態方法獲取某個型別的Type物件,例如typeof關鍵字和Type.GetType()方法。Type類提供了許多有用的方法,如GetMethods()獲取型別的所有方法,GetProperties()獲取型別的所有屬性等。

  2. MethodInfo類:MethodInfo類表示一個方法,可以通過Type類的GetMethods()方法獲取一個型別的所有方法,然後使用MethodInfo物件來呼叫具體的方法。

  3. PropertyInfo類:PropertyInfo類表示一個屬性,可以通過Type類的GetProperties()方法獲取一個型別的所有屬性,然後使用PropertyInfo物件來存取和修改具體的屬性。

  4. FieldInfo類:FieldInfo類表示一個欄位,可以通過Type類的GetFields()方法獲取一個型別的所有欄位,然後使用FieldInfo物件來存取和修改具體的欄位。

反射的優點

雖然反射在效能和資源消耗方面存在一些開銷,但它在應用中仍然具有一些重要的優勢和用途,如下所示:

  1. 動態載入和呼叫:反射允許在執行時動態載入和呼叫型別、方法和成員。這對於需要動態擴充套件和外掛化的應用程式非常有用,例如外掛系統、指令碼引擎等。通過反射,可以在執行時載入和使用不同的程式集和元件,從而使應用程式更具靈活性和可延伸性。

  2. 後設資料操作:反射提供了一種方式來讀取和操作型別的後設資料,包括屬性、欄位、方法、特性等的資訊。這使得我們可以在執行時動態獲取和操作型別的結構和行為。這對於實現某些高階功能和框架,例如ORM(物件關係對映)、序列化庫、依賴注入容器等非常有用。

  3. 可延伸的程式碼生成和編譯:反射使得我們可以動態生成和編譯程式碼。這對於一些需要在執行時動態生成和執行程式碼的場景非常有用,例如動態代理、AOP(面向切面程式設計)、程式碼生成器等。通過反射,我們可以在執行時建立並執行程式碼,從而實現更高階的程式碼生成和動態程式設計。

  4. 框架和工具的開發:反射是許多框架和工具的基礎,例如單元測試框架、序列化庫、ORM框架等。這些框架和工具需要在執行時通過反射來獲取和使用型別的資訊,並在不同的場景中動態呼叫和操作程式碼。通過反射,這些框架和工具可以更加靈活和通用,提供更高階的功能和擴充套件性。

需要強調的是,儘管反射在某些情況下會帶來效能開銷,但在大多數情況下,這些開銷並不會對應用程式的整體效能產生顯著的影響。在使用反射時,我們應該權衡其靈活性和便利性與效能之間的平衡,並根據實際需求來選擇合適的方法和工具。

 

反射的案例

 1 private void bt_Test_Click(object sender, System.Windows.RoutedEventArgs e)
 2 {
 3 //反射
 4         // 獲取MyClass型別的Type物件
 5         Type type = typeof(MyClass);
 6  7         // 建立MyClass物件
 8         object myClassObj = Activator.CreateInstance(type);
 9 10         // 獲取MyMethod方法的MethodInfo物件
11         MethodInfo methodInfo = type.GetMethod("MyMethod");
12 13         // 呼叫MyMethod方法
14         methodInfo.Invoke(myClassObj, null);
15 16         //Log.Write(str.ToString(),HaagonLibrary.Log.Log.EnumLogType.Warning);
17 18         Type type = typeof(MyClass);
19 20         // 動態呼叫反射方法
21         object myClassObj = Activator.CreateInstance(type);
22         MethodInfo methodInfo = type.GetMethod("MyMethod");
23 24         var stopwatch = Stopwatch.StartNew();
25         for (int i = 0; i < 1000000; i++)
26         {
27             methodInfo.Invoke(myClassObj, null);
28         }
29         stopwatch.Stop();
30         Log.Write("動態呼叫耗時:" + stopwatch.ElapsedMilliseconds + " 毫秒",                        HaagonLibrary.Log.Log.EnumLogType.Warning);
31         // 靜態呼叫反射方法
32         var myClass = new MyClass();
33 34         stopwatch.Restart();
35         for (int i = 0; i < 1000000; i++)
36         {
37             myClass.MyMethod();
38         }
39         stopwatch.Stop();
40         Log.Write("靜態呼叫耗時:" + stopwatch.ElapsedMilliseconds + " 毫秒", HaagonLibrary.Log.Log.EnumLogType.Warning);
41     }
42 }
43 public class MyClass
44 {
45     public void MyMethod()
46     {
47         Console.WriteLine("Hello, Reflection!");
48     }
49 }