之前做的都是獲取特性對象,都是查元數據的信息,現在我們可以通過反射開始動態的去創建對象和方法
1.兩種調用無參構造函數的方法:
創建一個DemoClass,里面有無參構造函數和有參構造函數
public class DemoClass { public string Name { get; set; } public int Age { get; set; } public DemoClass() { Console.WriteLine("無參構造函數被調用啦"); } public DemoClass(string name,int age) { this.Name = name; this.Age = age; Console.WriteLine("有參構造函數被調用了"); } }
(1)通過Assembly無參構造函數創建對象
Assembly assembly= Assembly.GetExecutingAssembly(); object o =assembly.CreateInstance("使用構造函數創建對象.DemoClass");
CreateInstance方法的第一個參數代表了要創建的類型實例的字符串名稱(命名空間+類名)。注意到CreateInstance方法返回的是一個Object對象,如果使用還要強制轉換一下。
(2)通過用Activator創建對象
object o2 = Activator.CreateInstance(null, "使用構造函數創建對象.DemoClass");
其中CreateInstance的第一個參數是程序集的名稱,為null時表示當前程序集;第二個參數是要創建的類型名稱。Activator.CreateInstance返回的是一個ObjectHandle對象,必須執行一次Unwrap()才能返回Object類型,進而可以強制轉換成其實際類型。ObjectHandle包含在System.Runtime.Remoting命名空間中,可見它是Remoting相關的,實際上ObjectHandle類只是一個對原類型進行了一個包裝以便進行封送
運行結果如下:

3.調用帶參構造函數創建對象
使用Assembly的createInstance函數進行對象的創建
public class Program { static void Main(string[] args) { Assembly assembly= Assembly.GetExecutingAssembly(); object[]paramers=new object[2];//創建參數數組,以便傳入 paramers[0] = ".net"; paramers[1] = 14; object o =assembly.CreateInstance("使用構造函數創建對象.DemoClass",true,BindingFlags.Default,null,paramers,null,null); DemoClass demo = (DemoClass)o; Console.WriteLine("輸出對象的信息:Name"+demo.Name+" Age"+demo.Age); Console.ReadKey(); } }
BindingFlags.Default不使用任何類型搜索策略。執行結果:

4.動態調用方法
在上面的DemoClass中添加兩個方法
public int Add(int x, int y) { Console.WriteLine("實例方法被調用"); return x + y; } public static void Add(double x, double y) { Console.WriteLine("靜態函數被調用"); }
(1)Type.InvokeMember調用實例方法
public class Program { static void Main(string[] args) { Type t = typeof(DemoClass); DemoClass demo=new DemoClass(); object[]parameters={1,2}; object result=t.InvokeMember("Add", BindingFlags.InvokeMethod, null, demo, parameters); Console.WriteLine("調用實例方法返回的結果:"+result); Console.ReadKey(); } }
第一個參數是指要調用的方法名,第二個參數是要調用方法,第三個Bingder幾乎永遠傳null,第四個是指要在哪個實例上操作,咱們新建的對象demo,最后一個參數是方法的傳入參數。InvokeMember方法被調用后返回執行結果。

(2)使用Type.InvokeMember調用靜態方法
public class Program { static void Main(string[] args) { Type t = typeof(DemoClass); object[]parameters={1.0,2.0}; object result=t.InvokeMember("Add", BindingFlags.InvokeMethod, null, t, parameters); Console.ReadKey(); } }
調用靜態方法時與調實例方法差別在第四個參數上,調靜態方法只需要傳遞類型就可以。
5.使用MethodInfo.Invoke調用方法
先獲取一個MethodInfo實例,然后調用該實例的Invoke方法
(1)調用實例方法
public class Program { private static void Main(string[] args) { Type t = typeof(DemoClass); object[] parameters = { 1, 2 }; DemoClass demo = new DemoClass(); MethodInfo info = t.GetMethod("Add", BindingFlags.Instance | BindingFlags.Public); info.Invoke(demo, parameters); Console.ReadKey(); } }
因為方法中存在多個“Add”方法,所以在GetMethod中加BindingFlags中是必要的,Invoke方法第一個參數是要在那個實例上調用該方法,第二個參數時參數列表。Invoke返回方法執行結果。
(2)調用靜態方法
public class Program { private static void Main(string[] args) { Type t = typeof(DemoClass); object[] parameters = { 1, 2 }; MethodInfo info = t.GetMethod("Add", BindingFlags.Static | BindingFlags.Public); info.Invoke(null, parameters); Console.ReadKey(); } }
調用靜態方法與實例方法的區別在於在用BingdingFlags進行搜索時要指定搜索Static,另外Invoke的時候不需要再傳入類型的實例了。
6.遲綁定
在我們項目中,各個插件實現了同一個插件接口,再運行時動態的去加載哪個插件,如果不使用反射動態調用的情況下,只能去寫多個if else了。編譯器在運行前根本不知道去執行哪個方法,稱為遲綁定。
