通過反射動態創建對象、方法


之前做的都是獲取特性對象,都是查元數據的信息,現在我們可以通過反射開始動態的去創建對象和方法

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了。編譯器在運行前根本不知道去執行哪個方法,稱為遲綁定。


免責聲明!

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



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