標籤:
反射
放射是指在程式運行時動態擷取類的資訊的機制,我們下面來看看C#中的反射。
Type
Type 為 System.Reflection 功能的根,也是訪問中繼資料的主要方式。 使用 Type 的成員擷取關於型別宣告的資訊,如建構函式、方法、欄位、屬性 (Property) 和類的事件,以及在其中部署該類的模組和程式集。
我們擷取一個指定類型的Type有三種方法:
- 通過typeof直接擷取;
- 通過調用GetType方法擷取;
- 通過調用Type的靜態方法GetType擷取;
這三個方法都可以擷取指定類型的Type對象,但是也有一點區別,具體可以參考下面兩篇部落格:
http://www.studyofnet.com/news/284.html
http://blog.csdn.net/letianok/article/details/7257117
下面我們來看一個例子:
1 using System; 2 3 namespace Study 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Type t1 = typeof(string);10 Console.WriteLine(t1.FullName);11 //System.String12 13 Type t2 = "hello type!".GetType();14 Console.WriteLine(t2.FullName);15 //System.String16 17 Type t3 = Type.GetType("System.String", false);18 Console.WriteLine(t3.FullName);19 //System.String20 21 Console.Read();22 }23 }24 }擷取類的資訊
我們可以通過Type類型擷取到類的所有資訊,比如我們要擷取類的所有方法資訊的話,可以使用下面的代碼:
1 using System; 2 using System.Reflection; 3 4 namespace Study 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 {10 string str = "Hello Type!";11 12 Type t = str.GetType();13 //擷取所有方法資訊14 MethodInfo[] methodInfos = t.GetMethods();15 for (int i = 0; i < methodInfos.Length; i++)16 {17 Console.WriteLine(methodInfos[i].Name);18 }19 //僅擷取非靜態公用方法資訊20 methodInfos = t.GetMethods(BindingFlags.Instance | BindingFlags.Public);21 for (int i = 0; i < methodInfos.Length; i++)22 {23 Console.WriteLine(methodInfos[i].Name);24 }25 26 Console.Read();27 }28 }29 }
更多資訊的擷取方法可以參考說明文檔(https://msdn.microsoft.com/zh-cn/library/system.type(v=vs.110).aspx)。
調用指定的方法
下面我們看看如何擷取一個類的指定方法並進行調用:
1 using System; 2 using System.Reflection; 3 4 namespace Study 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 {10 string str = "Hello Type!";11 12 Type t = str.GetType();13 //對於存在多個重載的方法需要指明參數的類型14 MethodInfo method = t.GetMethod("Split", new []{typeof(char[])});15 //調用方法16 string[] strs = method.Invoke(str, new object[] {new[] {‘ ‘}}) as string[];17 for (int i = 0; i < strs.Length; i++)18 {19 Console.WriteLine(strs[i]);20 }21 22 Console.Read();23 }24 }25 }Assembly
程式集可以看做一個或多個DLL或EXE檔案的集合,可以通過程式集將重複的代碼提取出來,可以重複使用。
我們首先建立一個類庫項目,代碼如下:
1 namespace StudyLib 2 { 3 public class MyClass 4 { 5 public int Add(int a, int b) 6 { 7 return a + b; 8 } 9 10 public int Add(int a, int b, int c)11 {12 return a + b + c;13 }14 }15 }
然後點擊功能表列-》產生-》產生XXX,可以獲得對應的DLL檔案,接下來我們使用Assembly讀取DLL並執行其中的方法:
1 using System; 2 using System.Reflection; 3 4 namespace Study 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 {10 Assembly assembly = Assembly.LoadFrom("E:\\study\\C#\\StudyLib\\StudyLib\\bin\\Debug\\StudyLib.dll");11 12 //輸出所有類型名稱13 Type[] types = assembly.GetTypes();14 for (int i = 0; i < types.Length; i++)15 {16 Console.WriteLine(types[i].FullName);17 }18 //StudyLib.MyClass19 20 //動態建立類並調用其中的方法21 Type t = assembly.GetType("StudyLib.MyClass");22 ConstructorInfo constructor = t.GetConstructor(Type.EmptyTypes);23 Object myClass = constructor.Invoke(new object[]{});24 25 MethodInfo method1 = t.GetMethod("Add", new[] {typeof (int), typeof (int)});26 int result1 = (int)method1.Invoke(myClass, new object[] {100, 123});27 Console.WriteLine("第一個方法返回: " + result1);28 //第一個方法返回: 22329 30 MethodInfo method2 = t.GetMethod("Add", new[] { typeof(int), typeof(int), typeof(int)});31 int result2 = (int)method2.Invoke(myClass, new object[] { 100, 123, 456 });32 Console.WriteLine("第二個方法返回: " + result2);33 //第二個方法返回: 67934 35 Console.Read();36 }37 }38 }
C#學習筆記(十):反射