C#反射

一.什麼是反射?

 反射 Reflection 是提供封裝程序集、模塊和類型的對象

程序集包含模塊,而模塊包含類型,類型又包含成員。反射則提供了封裝程序集、模塊和類型的對象。您可以使用反射動態地創建類型的實例,將類型綁定到現有對象,或從現有對象中獲取類型。然後,可以調用類型的方法或訪問其字段和屬性。

二.反射的用途

1.使用 Assembly 定義和加載程序集,加載在程序集清單中列出的模塊,以及從此程序集中查找類型並創建該類型的實例。

2.使用 Module 瞭解如下的類似信息:包含模塊的程序集以及模塊中的類等。您還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。

3.使用 ConstructorInfo 瞭解如下的類似信息:構造函數的名稱、參數、訪問修飾符(如 public 或 private)和實現詳細信息(如 abstract 或 virtual)等。
4.使用 Type 的 GetConstructors 或 GetConstructor 方法來調用特定的構造函數。

5.使用 MethodInfo 來了解如下的類似信息:方法的名稱、返回類型、參數、訪問修飾符(如 public 或 private)和實現詳細信 息(如 abstract 或 virtual)等。使用 Type 的
GetMethods 或 GetMethod 方法來調用特定的方法。
6.使用 FieldInfo 來了解如下的類似信息:字段的名稱、訪問修飾符(如 public 或 private)和實現詳細信息(如 static)等;並獲取或設置字段值。
7.使用 EventInfo 來了解如下的類似信息:事件的名稱、事件處理程序數據類型、自定義屬性、聲明類型和反射類型等;並添加或移除事件處理程序。
8.使用 PropertyInfo 來了解如下的類似信息:屬性的名稱、數據類型、聲明類型、反射類型和只讀或可寫狀態等;並獲取或設置屬性值。
9.使用 ParameterInfo 來了解如下的類似信息:參數的名稱、數據類型、參數是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。
 
三.實例
首先,我們創建一個普通的類庫項目Alex.Reflector。如圖 
 
具體代碼如下:
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 namespace Alex.Reflector
 6 {
 7     public class ReflectorTest
 8     {
 9         
10         public string Name { get; set; }
11         /// <summary>
12         /// 靜態方法
13         /// </summary>
14         /// <param name="name"></param>
15         /// <returns></returns>
16         public static string StaticMethod(string name)
17         {
18             return name;
19         }
20         /// <summary>
21         /// 實例方法
22         /// </summary>
23         /// <param name="name"></param>
24         /// <returns></returns>
25         public string GetNameExample(string name)
26         {
27             return "Hi" + name;
28         }
29         /// <summary>
30         /// 無參的方法
31         /// </summary>
32         /// <returns></returns>
33         public string GetNoParameter()
34         {
35             return "沒有參數";
36         }
37     }
38 }

我們生成該類庫項目會在Bin目錄下生成一個Alex.Reflector.dll(根據你項目的名字,這裏只是舉例)的文件。

接下來。我們就要用我們的 "反射"技術來操作我們這個DLL文件。

 

在當前解決方案下新建一個項目名爲 Alex.ReflectorDemo,如圖

然後在此項目下新建一個頁面,我們暫時命名爲ReflectorTest.aspx 整體結構如圖

ReflectorTest.aspx源碼如下

 1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReflectorTest.aspx.cs" Inherits="Alex.ReflectorDemo.ReflectorTest" %>
 2 
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4 
 5 <html xmlns="http://www.w3.org/1999/xhtml">
 6 <head runat="server">
 7     <title>C#反射實例</title>
 8 </head>
 9 <body>
10     <form id="form1" runat="server">
11     <p>
12     <asp:Button ID="btn1" runat="server" Text="利用反射去調用程序集中(包含的類)所包含的方法,屬性,成員" onclick="btn1_Click" />
13     </p>
14     <asp:Label ID="lblShowMessage" runat="server" Text=""></asp:Label>
15     <p>
16         &nbsp;</p>
17     <p>
18         <asp:Button ID="btn2" runat="server" Text="利用反射獲取程序集中類,類的成員(方法,屬性等)" 
19             onclick="btn2_Click" />
20     </p>
21     <asp:Label ID="lblShowMessage1" runat="server" Text=""></asp:Label>
22     </form>
23 </body>
24 </html>

 

ReflectorTest.aspx.cs源碼如下。在這裏我就不一一解釋了。大家一看就懂。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.UI;
 6 using System.Web.UI.WebControls;
 7 using System.Reflection;
 8 
 9 namespace Alex.ReflectorDemo
10 {
11     public partial class ReflectorTest : System.Web.UI.Page
12     {
13         Assembly assembly;
14         Type type;
15         MethodInfo methodinfo;
16         protected void Page_Load(object sender, EventArgs e)
17         {
18 
19         }
20         /// <summary>
21         /// 利用反射去調用程序集中(包含的類)所包含的方法,屬性,成員
22         /// </summary>
23         /// <param name="sender"></param>
24         /// <param name="e"></param>
25         protected void btn1_Click(object sender, EventArgs e)
26         {
27             try
28             {
29                 assembly = Assembly.LoadFile(@"D:\My\Reflector\Alex.Reflector\Alex.Reflector\bin\Debug\Alex.Reflector.dll");//根據DLL的物理路徑加載
30                 type = assembly.GetType("Alex.Reflector.ReflectorTest");//根據類型名稱反射出該類型,注意看格式是命名空間.類名
31                 object strobject = Activator.CreateInstance(type);//創建該類型的對象實例
32                 methodinfo = type.GetMethod("GetNameExample");//反射獲取方法。實例方法
33                 string s = (string)methodinfo.Invoke(strobject, new string[] { "田小賤" });
34                 lblShowMessage.Text = "調用實例方法返回:" + s.ToString()+"</br>";
35 
36                 methodinfo = type.GetMethod("StaticMethod");
37                 string s1 = (string)methodinfo.Invoke(null, new string[] { "肖小仙" });
38                 lblShowMessage.Text += "調用靜態方法返回:" + s1.ToString();
39                 type.GetProperty("Name").SetValue(strobject, "田小賤", null);
40             }
41             catch (Exception)
42             {
43                 throw;
44             }
45             finally
46             {
47                 assembly = null;
48                 type = null;
49                 methodinfo = null;
50                 
51             }
52         }
53         /// <summary>
54         /// 利用反射獲取程序集中類,類的成員(方法,屬性等)
55         /// </summary>
56         /// <param name="sender"></param>
57         /// <param name="e"></param>
58         protected void btn2_Click(object sender, EventArgs e)
59         {
60             assembly = Assembly.LoadFile(@"D:\My\Reflector\Alex.Reflector\Alex.Reflector\bin\Debug\Alex.Reflector.dll");//根據DLL的物理路徑加載
61             Module[] module = assembly.GetModules();//獲取作爲程序集的一部分的所有模塊
62             Type[] types = assembly.GetTypes(); //獲取程序集中定義的所有類型
63 
64             foreach (var item in types)
65             {
66                 lblShowMessage1.Text ="所包含的類型名稱:"+ item.Name+"</br>";
67                 MethodInfo[] methodinfos=item.GetMethods();//  (MethodInfo)發現方法的屬性,並提供對方法元數據的訪問)獲取該類型下所包含的方法信息
68                 foreach (var method in methodinfos)
69                 {
70                     lblShowMessage1.Text += "該類所包含的方法名稱:"+method.Name+"</br>";
71                 }
72                 PropertyInfo[] propertyInfo = item.GetProperties();//(ProperInfo)發現屬性的特性,並提供對該屬性元數據的訪問
73 
74                 foreach (var property in propertyInfo)
75                 {
76                     lblShowMessage1.Text += "該類所包含的屬性名稱:" + property.Name; ;
77                 }
78             }
79 
80         } 
81     }
82 }
View Code

多話不說,直接看運行效果。

最後。提醒大家一下。反射相對來說會影響性能。 希望大家根據自己實際情況去合理使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章