【C#】:淺談反射機制
什麼是反射?
反射提供了封裝程式集、模組和型別的物件(Type 型別)。可以使用反射動態建立型別的例項,將型別繫結到現有物件,或從現有物件獲取型別並呼叫其方法或訪問其欄位和屬性。如果程式碼中使用了屬性,可以利用反射對它們進行訪問。
反射機制是.Net中獲取執行時型別資訊的方式,.Net的應用程式由幾個部分:‘程式集(Assembly)’、‘模組(Module)’、‘型別(class)’組成,而反射提供一種程式設計的方式,讓程式設計師可以在程式執行期獲得這幾個組成部分的相關資訊。
通俗的來講,就是反射是通過一個物件去了解另一個物件的內部結構和資訊,即使在你不知道那個物件存在的情況下。就好比是海船的聲納探測一樣,我們並不知道海水深處是什麼情況,但是通過聲吶反射回來的情況,就可以掌握障礙物的大小,移動速度等等,和我們所談論的反射是一個道理。但是我們在程式使用反射不僅可以獲取,類的內部情況,還可以操作呼叫反射類的方法,簡直是太神奇了。
為什麼用反射?
1使用了反射後,你的程式在更新的時候無需重新編譯,只要將更新的Dll換掉即可完成程式的更新和升級。
2將反射和配置檔案相結合,可以開發出功能隨意增刪改的軟體,具備了極大地靈活性和擴充套件性。
3反射提高了程式的靈活性,降低了耦合性,提高了自適應能力,同時也大大提高了程式的複用性。
但是要強調的一點是,任何事物都有兩面性,不是所有場合都適合使用反射技術的。使用反射也會有其缺點:
1首先帶來的一個很大的問題就是——效能問題,使用反射基本上是一種解釋操作,用於欄位和方法接入時要遠慢於直接程式碼。
2使用反射會使程式內部邏輯模糊化,程式設計師在除錯程式碼的時候西瓦昂看到清晰的程式邏輯,而反射卻繞過了原始碼,因此會帶來一定的維護性問題,同時反射程式碼比相應的直接程式碼更加複雜。
綜上所述:反射機制有其適用的場合,只要用來開發對靈活性和擴充套件性要求很高的軟體系統,普通的程式沒必要使用。
怎麼用反射?
首先宣告我對反射的使用不是很深入,只是做了一些簡單的嘗試,下面用一個小Demo來說明如何在C#中使用反射獲取一個類的屬性、方法以及修改屬性和呼叫方法等。程式碼如下:
首先我們先寫一個目標類Student
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ITOO.Reflection.Student
{
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
// 預設建構函式
public Student()
{
this.Age = 24;
this.Name = "連江偉";
}
//帶引數的建構函式
public Student(string name,int age)
{
this.Name = name;
this.Age = age;
}
public void Hello()
{
Console.WriteLine("我是"+Name +",我今年"+Age +"歲了!");
}
}
}</span>
然後我們在控制檯應用程式中去利用反射操縱這個類
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace ITOO.Reflection.Client
{
class Program
{
static void Main(string[] args)
{
//動態載入DLL,這個LoadFile最方便,引數就是dll的路徑。
var asm = Assembly.LoadFile(@"C:\Users\ljw\Desktop\學習例子\ITOO.Reflection.Test\ITOO.Reflection.Student\bin\Debug\ITOO.Reflection.Student.dll");
//獲取Student類的型別
var type = asm.GetType("ITOO.Reflection.Student.Student");
//建立該類的例項
var instance = asm.CreateInstance("ITOO.Reflection.Student.Student");
//為學生類的屬性賦值
type.GetProperty("Name").SetValue(instance, "段天涯", null);
type.GetProperty("Age").SetValue(instance, 18, null);
//獲取Student類的方法
var method = type.GetMethod("Hello");
//呼叫Student類的成員方法Hello
method.Invoke(instance, null);
Console.Read();
}
}
}</span>
小結一下:對於反射這個概念,一開始我是比較模糊的,雖然很多次的聽到別人在說在講,但是由於沒有自己去查資料去研究,去動手程式碼實現,終究不能感同身受,理解其中的原理和思想,如今閱讀了大量的部落格和文章之後,又動手實踐了一下,有了一些淺淺的理解,由於Donet的反射機制是封裝好的,所以對於反射內部實現原理還不清楚,期待以後能夠繼續深入學習。