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

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

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

搞點反射,能夠提升程序的靈活性、可擴展性、耦合度。spa

 

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

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

 

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

給爺爪巴繼承

使用反射是要分場合的教程

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

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

還有一件事,若是你程序全用的反射。一時反射一時爽,後期維護秒跑路。

程序員最煩的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的時候才能,把基類的也輸出出來。

相關文章
相關標籤/搜索