程序集和反射(二)


     上篇文章主要介紹了程序集的內容:程序集和反射(一),時隔這么久,今天終於騰出點時間,把反射部分的知識點給整理一下,不把這個寫完,心里總覺得有點堵。對於反射,我相信很多人跟LZ一個德行,不會,所以不用,不用,所以永遠不會。

     通過System.Reflection命名空間中的類已經System.Type,您可以獲取有關已加載的程序集和在其中定義的類型(如類、接口、值類型)的信息。您也可以使用反射在運行時創建類型實例,以及調用和訪問這些實例。

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

    反射通常具有以下用途:

  • 類型 作用
    Assembly 定義和加載程序集,加載在程序集清單中列出的模塊,以及從此程序集中查找類型並創建該類型的實例。用來獲取程序集內部信息
    EventInfo 發現以下信息:事件的名稱、事件處理程序數據類型、自定義特性、聲明類型和反射類型等;並添加或移除事件處理程序。
    FieldInfo  發現以下信息:字段的名稱、訪問修飾符(如 public 或 private)和實現詳細信息(如 static)等;並獲取或設置字段值 。該類保存給定的字段信息
    MethodInfo 發現以下信息:方法的名稱、返回類型、參數、訪問修飾符(如 public 或 private)和實現詳細信息(如 abstract 或 virtual)等。 使用 Type 的 GetMethods 或 GetMethod 方法來調用特定的方法。該類保存給定的方法信息
    MemberInfo 該類是一個基類,它定義了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多個公用行為
    Module 發現以下信息:包含模塊的程序集以及模塊中的類等。 您還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。該類可以使你能訪問多個程序集中的給定模塊
    ParameterInfo 發現以下信息:參數的名稱、數據類型、參數是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。該類保存給定的參數信息      
    PropertyInfo 發現以下信息:屬性的名稱、數據類型、聲明類型、反射類型和只讀或可寫狀態等;並獲取或設置屬性值。該類保存給定的屬性信息
  • 使用 ConstructorInfo 發現以下信息:構造函數的名稱、參數、訪問修飾符(如 public 或 private)和實現詳細信息(如 abstract 或 virtual)等。 使用 Type 的 GetConstructors 或 GetConstructor 方法來調用特定的構造函數。(以上內容參考MSDN)

 Type類

          表示類型聲明:類類型、接口類型、數組類型、值類型、枚舉類型、類型參數、泛型類型定義,以及開放或封閉構造的泛型類型。

           可以通過以下兩種方式獲得Type:

                 1.通過類獲得Type:   Type t=typeof(Person);

                 2.通過對象獲得Type:Person p=new Person();  Type t=p.GetType();

           這里仍然采用上篇文章中的示例:

 1       static void Main(string[] args)
 2         {
 3             //通過反射動態調用另一個程序集中的方法
 4             //1加載程序集
 5             string path = AppDomain.CurrentDomain.BaseDirectory;//獲取當前.exe執行文件的路徑
 6             path = Path.Combine(path, "MyAssembly.dll");//拼接程序集的路徑
 7             Assembly assembly = Assembly.LoadFile(path);
 8             //2創建Person類的對象
 9             Type type = assembly.GetType("MyAssembly.Person");
10             object o = Activator.CreateInstance(type,"wolf",22,"未知");//實例化
11             //3獲取方法的類型
12              MethodInfo methodInfo = type.GetMethod("SayHi");
13             //4反射調用方法
14              methodInfo.Invoke(o, null);
15             Console.Read();
16         }

    調用Assembly的GetExportedTypes方法可以得到Assembly中定義的所有的public類型。

    調用Assembly的GetTypes()方法可以得到Assembly中定義的所有的類型。

    調用Assembly的GetType(name)方法可以得到Assembly中定義的全名為name的類型信息。如: Type type = assembly.GetType("MyAssembly.Person");

動態創建對像

     Activator.CreateInstance(Type t)會動態調用類的無參構造函數創建一個對象,返回值就是創建的對象,如果類沒有無參構造函數就會報錯。

     GetConstructor(參數列表);//這個是找到帶參數的構造函數。例如:object o = Activator.CreateInstance(type,"wolf",22,"未知");//實例化

Type類的方法

     bool IsAssignableFrom(Type c):判斷當前的類型的變量是不是可以接受c類型變量的賦值。

1             Type type = assembly.GetType("MyAssembly.Person");
2             Type studentType = assembly.GetType("MyAssembly.Student");
3             Console.WriteLine(type.IsAssignableFrom(studentType));

      Result:True      因為Person p=new Student();

     typeof(IPlugin).IsAssignableFrom(t)   

     bool IsInstanceOfType(object o):判斷對象o是否是當前類的實例(當前類可以是o的類、父類、接口)  

                Person p = new Student();
        
                //判斷p是否是一個Student類的實例

                 bool r = typeof(Student).IsInstanceOfType(p);//True

 

     bool IsSubclassOf(Type c):判斷當前類是否是類c的子類。實用於類,不適用於接口

//判斷Student是否是Person的子類
bool r = typeof(Student).IsSubclassOf(typeof(Person));//Tru

     IsAbstract,判斷是否為抽象的,含接口

 //判斷Person是否是抽象類或接口
 bool r = typeof(Person).IsAbstract;//False

 動態調用成員

    MemberInfo類  抽象類,有很多子類,下面講的類都繼承自它,獲取程序集成員的相關信息(類型、方法、事件、字段和屬性)

    PropertyInfo  獲取屬性

    主要成員:CanRead、CanWrite、PropertyType屬性類型;SetValue、GetValue:讀取值,設置值,第一個參數是實例對象,因為set、get要針對具體實例,最后一個參數null。pInfo.SetValue(p1, 30, null)

    MethodInfo  獲取方法

    MethodInfo   都是和具體對象不相關的,所以需要第一個參數指定要執行的對象。

//3獲取方法的類型
MethodInfo methodInfo = type.GetMethod("SayHi");

    FieldInfo     獲取字段

    EventInfo     獲取事件

案例:

 

<?xml version="1.0" encoding="utf-8" ?>
<Persons>
  <person>
    <Name>wolfy1</Name>
    <Age>22</Age>
    <Gender></Gender>
  </person>
  <person>
    <Name>wolfy2</Name>
    <Age>23</Age>
    <Gender></Gender>
  </person>
  <person>
    <Name>wolfy3</Name>
    <Age>24</Age>
    <Gender>未知</Gender>
  </person>
</Persons>
Person

 

     控制台程序測試程序:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.IO;
 6 using System.Reflection;
 7 using System.Xml;
 8 using System.Xml.Linq;
 9 namespace AssemblyDemo
10 {
11     class Program
12     {
13 
14         static void Main(string[] args)
15         {
16             //通過反射動態調用另一個程序集中的方法
17             //1加載程序集
18             string path = AppDomain.CurrentDomain.BaseDirectory;//獲取當前.exe執行文件的路徑
19             string xmlPath = Path.Combine(path, "Person.xml");
20             path = Path.Combine(path, "MyAssembly.dll");//拼接程序集的路徑
21             XElement xml;
22             Assembly assembly = Assembly.LoadFile(path);
23             xml = XElement.Load(xmlPath);
24             //2創建Person類的對象
25             Type type = assembly.GetType("MyAssembly.Person");
26             foreach (var item in xml.Elements("person"))
27             {
28                 PropertyInfo[] properties = type.GetProperties();
29                 foreach (PropertyInfo p in properties)
30                 {
31                     Console.Write(item.Element(p.Name).Value+"\t");
32                 }
33                 Console.WriteLine();
34             }
35             Console.Read();
36         }
37     }
38 }

      結果:

      

 

 結語:

       關於程序集和反射的基礎,就介紹到這里,怎么樣去掌握,還得勤思考,多用才行。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM