深入淺出 .NET C# 反射技術


反射這個詞聽起來就很牛逼是吧?

嗯的確,反射是比較高級的特性,只有語言基礎很扎實的Dev們才應該使用它。

搞點反射,可以提高程序的靈活性、可擴展性、耦合度。

 

反射這東西,是為了動態地運行時加載,相比於靜態代碼。編譯的時候就是板上釘釘了。

就是說,如果你的程序需要在運行時搞一些晚綁定,動態加載或檢查對象之類的操作時,那么反射歡迎你。

 

說到這,也許有人立刻就去找反射相關的文檔和教程,想趕緊把反射技術實踐到程序上。

給爺爪巴

使用反射是要分場合的

反射基本上是一種解釋操作,用於字段啊方法啊接入時要遠慢於直接擼代碼。

因此反射機制主要應用在對靈活性和拓展性要求很高的東西上,普通程序不建議使用。

還有一件事,如果你程序全用的反射。一時反射一時爽,后期維護秒跑路。

程序員最煩的2件事是什么,維護沒有注釋的代碼和寫注釋。但當程序員看到代碼有一大堆的反射而且沒寫注釋的時候,他們會直接/kill @p就完事了。

因為 反 射 繞 過 了 源 代 碼 的 技 術 ,反射代碼賊JB復雜,相比普通的來說

 

BCL聲明了一個Type類型(它是抽象類),用來包含類型的特性。使用這個類的對象能讓我們獲取程序使用的類型的信息。

由於Type是抽象類,所以它不能被實例化。而是在運行時,CLR創建從Type(RuntimeType)派生的類型的實例。當我們要訪問這些實例的時候,CLR不會返回派生類的引用而是返回Type基類的引用。

關於Type有如下重要的點:

①對於程序每一個需要用到的類型,CLR會穿件一個包含這個類型信息的Type類型的對象(真實的是上面說的派生的類型的實例)。

②程序中用到的每一個類型都會關聯到獨立的Type類的對兩個象。

③無論創建的類型有多少個實例,只有一個Type對象會關聯到所有這些實例。就像下面的圖表示的一樣。創建了一個OtherClass的實例oc、以及兩個MyClass的實例mc1和mc2,但是在堆上都只會有一個Type對象來的對應他們,如下面的圖示:

 

 

 

現在我們知道,object類型包含了一個GetType方法,它可以用來返回事例的Type對象引用。由於所有的類都是繼承自object類型,所以所有的類都可以調用GetType來獲得Type類型對象的引用。

所以下面的代碼,在遍歷派生類的Field的時候才能,把基類的也輸出出來。

//雞肋
class BaseClass
{
    public int BaseField = 0;
}

//派生類
class DerivedClass : BaseClass
{
    public int DerivedField = 0;
}

class Program
{
    static void Main(string[] args)
    {
        var bc = new BaseClass();
        var dc = new DerivedClass();
        BaseClass[] bca = new BaseClass[] { bc, dc };
        foreach(var v in bca)
        {
            //獲取類型
            Type t = v.GetType();
            Console.WriteLine("Object Type: {0}", t.Name);
            //獲取類中的字段
            FieldInfo[] fi = t.GetFields();
            foreach (var f in fi)
                Console.WriteLine("     Field:{0}", f.Name);
            Console.WriteLine();
        }
        Console.WriteLine("End!");
        Console.ReadKey();
    }
}

 

 

 

方法二:通過typeof()方法來獲取一個類型的Type對象引用。例如下面的代碼:

1
Type t =  typeof (DerivedClass);

 

 

 

//通過程序集獲取類型
var baseType = Assembly.GetExecutingAssembly().GetType("TestDemo.BaseClass");
var derivedType = Assembly.GetExecutingAssembly().GetType("TestDemo.DerivedClass");

  

很好,來個常用的騷操作。結合GetType和typeof操作,可以做很多事情....

static void Main(string[] args)
{
    var intArray = typeof(int).MakeArrayType();
    var int3Array = typeof(int).MakeArrayType(3);

    Console.WriteLine($"是否是int 數組 intArray == typeof(int[]) :{intArray == typeof(int[]) }");
    Console.WriteLine($"是否是int 3維數組 intArray3 == typeof(int[]) :{int3Array == typeof(int[]) }");
    Console.WriteLine($"是否是int 3維數組 intArray3 == typeof(int[,,]):{int3Array == typeof(int[,,]) }");

    //數組元素的類型
    Type elementType = intArray.GetElementType();
    Type elementType2 = int3Array.GetElementType();

    Console.WriteLine($"{intArray}類型元素類型:{elementType }");
    Console.WriteLine($"{int3Array}類型元素類型:{elementType2 }");

    //獲取數組的維數
    var rank = int3Array.GetArrayRank();
    Console.WriteLine($"{int3Array}類型維數:{rank }");
    Console.ReadKey();
}

 

未完待續...

所以下面的代碼,在遍歷派生類的Field的時候才能,把基類的也輸出出來。


免責聲明!

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



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