反射學習筆記

反射的定義:編程

反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲反射機制。數組


反射機制主要提供瞭如下功能:
在運行時判斷任意一個對象所屬的類;
在運行時構造任意一個類的對象;
在運行時判斷任意一個類所具備的成員變量和方法;
在運行時調用任意一個對象的方法;
生成動態代理。ide

 

另一種解釋:函數

反射是編程讀取與類型相關聯的元數據的行爲。this

.Net源代碼是兩次編譯,一次執行的。在Visual Studio通過第一次編譯生成程序集(.exe,.dll),就是IL(中間語言)和元數據,而後在通過CLR(公共語言運行庫),將程序集編譯成機器代碼,機器代碼在交給cpu去執行。spa

在程序中,當咱們須要動態的去加載程序集的時候(將對程序集的引用由編譯時推移到運行時),反射是一種很好的選擇。反射爲.NET類型提供了高度的動態能力,包括:元數據的動態查詢、綁定與執行、動態代碼生成。經常使用的反射類型包含在System.Reflection和System.Reflection.Emit,反射包括程序集反射、類型反射、接口反射、類型成員反射。.net

 

經過反射能夠提供類型信息,從而使得咱們開發人員在運行時可以利用這些信息構造和使用對象。3d

反射機制運行程序在執行過程當中動態地添加各類功能。代理

反射是一種寬泛的叫法,它經過 System.Reflection 命名空間 並 配合 System.Type 類,提供了在運行時(Runtime)對於 類型和對象(及其成員)的基本信息 以及 元數據(metadata)的訪問能力。code

 

 

反射實例:

添加一個基本實例,包含兩個構造函數兩個方法,下面實例介紹如何使用反射的方式建立對象以及調用其中的方法。

namespace ConsoleDmeo.DesignPattern.ReflectionDemo
{
    public class Calculator
    {
        private int x;
        private int y;

        public Calculator()
        {
            x = 0;
            y = 0;
        }

        public Calculator(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public int Add()
        {
            int total = 0;
            total = x + y;
            Console.WriteLine("Invoke Instance Method: ");
            Console.WriteLine(String.Format("[Add]: {0} plus {1} equals to {2}", x, y, total));
            return total;
        }

        public static int Add(int x, int y)
        {
            int total = x + y;
            Console.WriteLine("Invoke Static Method: ");
            Console.WriteLine(String.Format("[Add]: {0} plus {1} equals to {2}", x, y, total));
            return total;
        }
    }
}
View Code

 

string assemblyName = "ConsoleDmeo.DesignPattern.ReflectionDemo";//程序集名稱
string className = "Calculator";//類名

首先使用反射的方式調用無參構造函數建立對象,兩種方式:

使用Assembly的CreateInstance方法 無參
CreateInstance的第一個參數表明了要建立的類型實例的字符串名稱,第二個參數說明是否是大小寫無關(Ignore Case)。
注意到CreateInstance返回的是一個Object對象,意味着若是想使用這個對象,須要進行一次類型轉換。

Assembly assembly = Assembly.GetExecutingAssembly();
Object obj = assembly.CreateInstance(assemblyName + "." + className);

還有一種寫法:Object obj22 = (Calculator)Assembly.Load("ConsoleDmeo").CreateInstance(assemblyName + "." + className);

 

調用Activator類的靜態方法CreateInstance
其中CreateInstance的第一個參數說明是程序集的名稱,爲null時表示當前程序集;第二個參數說明要建立的類型名稱。
Activator.CreateInstance返回的是一個ObjectHandle對象,必須進行一次Unwrap()才能返回Object類型,進而能夠強制轉換成咱們須要的類型(本例中是Calculator)

ObjectHandle objectHandle = Activator.CreateInstance(null, assemblyName + "." + className);
Object obj2 = objectHandle.Unwrap();

 

有參:

Assembly assembly2 = Assembly.GetExecutingAssembly();
Object[] parameters = new Object[2];
parameters[0] = 3;
parameters[1] = 5;
Object obj3 = assembly2.CreateInstance(assemblyName + "." + className, true, BindingFlags.Default, null,parameters, null, null);

 

調用方法的方式通常有兩種:

一、在類型的Type對象上調用InvokeMember()方法,傳遞想要在其上調用方法的對象(也就是剛纔動態建立的Calculator類型實例),並指定BindingFlags爲InvokeMethod。根據方法簽名,可能還須要傳遞參數。

須要說明的是,使用InvokeMember不限於調用對象的方法,也能夠用於獲取對象的字段、屬性,方式都是相似的,本文只說明最多見的調用方法。

在InvokeMember方法中,第一個參數說明了想要調用的方法名稱;第二個參數說明是調用方法(由於InvokeMember的功能很是強大,不光是能夠調用方法,還能夠獲取/設置 屬性、字段等。
第三個參數是Binder,null說明使用默認的Binder;第四個參數說明是在這個對象上(obj是Calculator類型的實例)進行調用;最後一個參數是數組類型,表示的是方法所接受的參數。

Type t = typeof (Calculator);
int result = (int) t.InvokeMember("Add", BindingFlags.InvokeMethod, null, obj2, null);

Object[] paramters2 = new Object[2];
paramters2[0] = 7;
paramters2[1] = 5;
int result2 = (int)t.InvokeMember("Add", BindingFlags.InvokeMethod, null, t, paramters2);

 

二、先經過Type對象的GetMethond()方法,獲取想要調用的方法對象,也就是MethodInfo對象,而後在該對象上調用Invoke方法。根據方法簽名,可能還須要傳遞參數。

MethodInfo methodInfo = t.GetMethod ("Add",BindingFlags.Instance | BindingFlags.Public );
int result3 = (int)methodInfo.Invoke(obj, null);

Object[] paramters3 = new Object[2];
paramters3[0] = 7;
paramters3[1] = 9;
MethodInfo methodInfo2 = t.GetMethod("Add", BindingFlags.Static | BindingFlags.Public);
int result4 = (int)methodInfo2.Invoke(null, paramters3);

 

、、

引用:

.Net 中的反射(動態建立類型實例) - Part.4

相關文章
相關標籤/搜索