【C#】:淺談反射機制

連江偉發表於2015-08-06

        什麼是反射?

        反射提供了封裝程式集、模組和型別的物件(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的反射機制是封裝好的,所以對於反射內部實現原理還不清楚,期待以後能夠繼續深入學習。

相關文章