當前位置:首頁 > IT技術(shù) > Windows編程 > 正文

C#中的反射
2021-08-07 23:39:58

一:什么是反射

C#編寫的程序會編譯成一個程序集(.DLL或.exe),其中會包含元數(shù)據(jù)、編譯代碼和資源,通過反射可以獲取到程序集中的信息
通俗來講,反射就是我們在只知道一個對象的外部而不了解內(nèi)部結(jié)構(gòu)的情況下,可以知道這個對象的內(nèi)部實現(xiàn)


二:反射的優(yōu)缺點

首先在編譯中分為動態(tài)編譯和靜態(tài)編譯,靜態(tài)編譯是在編譯中確定類型,綁定對象,而動態(tài)編譯是在運行中確定類型,綁定對象
反射的優(yōu)點就是可以動態(tài)創(chuàng)建對象、綁定對象,提高了程序的靈活性和擴展性,但反射是一種解釋操作,在性能上不如靜態(tài)編譯快


三:通過Type類獲取程序集、模塊、類的相關(guān)信息

——Type類是一個抽象類,因此不能用他去實例化對象
——object類中定義了一個GetType方法,因此所有類都可以使用GetType()獲取到某一個對象所屬類的Type對象
——通過Type對象可以獲取到類中字段、屬性、方法、構(gòu)造函數(shù)等信息

using System;

class MainClass
{
    public static void Main(string[] args)
    {
        //1.通過對象獲取到這個對象所屬類的Type對象
        TestClass c = new TestClass();
        Type t = c.GetType();

        //2.通過Type類中的靜態(tài)方法GetType獲取到類的Type對象
        //Type t = Type.GetType("TestClass");

        //3.通過typeof關(guān)鍵字獲取到類的Type對象
        //Type t = typeof(TestClass);

        Console.WriteLine(t.Name);//獲取類名(不帶命名空間)
        Console.WriteLine(t.FullName);//獲取類名(帶命名空間)
        Console.WriteLine(t.Assembly);//獲取程序集
        Console.WriteLine(t.BaseType);//獲取基類類型

        Console.WriteLine("----------獲取類中字段");
        var fields = t.GetFields();
        foreach (var temp in fields)
        {
            Console.WriteLine(temp.Name);
        }

        Console.WriteLine("----------獲取類中屬性");
        var properties = t.GetProperties();
        foreach (var temp in properties)
        {
            Console.WriteLine(temp.Name);
        }

        Console.WriteLine("----------獲取類中方法");
        var methods = t.GetMethods();
        foreach (var temp in methods)
        {
            Console.WriteLine(temp.Name);
        }

        Console.WriteLine("----------獲取類中成員");
        var members = t.GetMembers();
        foreach (var temp in members)
        {
            Console.WriteLine(temp.Name);
        }

        Console.WriteLine("----------獲取類中嵌套類");
        var nesteds = t.GetNestedTypes();
        foreach (var temp in nesteds)
        {
            Console.WriteLine(temp.Name);
        }

        Console.WriteLine("----------獲取類中構(gòu)造函數(shù)");
        var constructors = t.GetConstructors();
        foreach (var temp in constructors)
        {
            Console.WriteLine(temp.Name);
        }
    }
}

public class TestClass
{
    public string str;
    public int num { get; set; }
    public void Fun()
    {

    }
    public class TestNestedClass
    {

    }
}

得到一個Type類型對象有三種方法:object.GetType()、Type.GetType()、typeof()
使用object.GetType()必須先創(chuàng)建一個實例,而后兩種不需要創(chuàng)建實例,但使用typeof運算符仍然需要知道類型的編譯時信息,Type.GetType()靜態(tài)方法不需要知道類型的編譯時信息,所以是首選方法


四:創(chuàng)建實例:性能上要比new差

——通過Activator創(chuàng)建實例

using System;

class MainClass
{
    public static void Main(string[] args)
    {
        object c = Activator.CreateInstance(typeof(TestClass), "hello world");
        Console.WriteLine(((TestClass)c).str);
    }
}

public class TestClass
{
    public string str;
    public TestClass(string str)
    {
        this.str = str;
    }
}

?

?

——通過構(gòu)造函數(shù)創(chuàng)建實例

using System;

class MainClass
{
    public static void Main(string[] args)
    {
        Type t = typeof(TestClass);
        Type[] paramTypes = new Type[1] { typeof(string) };
        var info = t.GetConstructor(paramTypes);
        object[] param = new object[1] { "hello world" };
        var o = info.Invoke(param);

        Console.WriteLine(((TestClass)o).str);
    }
}

public class TestClass
{
    public string str;
    public TestClass(string str)
    {
        this.str = str;
    }
}

五:反射賦值

using System;
using System.Reflection;

class MainClass
{
    public static void Main(string[] args)
    {
        TestClass cc = new TestClass();
        Type t = cc.GetType();
        FieldInfo info = t.GetField("str");
        info.SetValue(cc, "hello world");
        Console.WriteLine(info.GetValue(cc)); 
    }
}

public class TestClass
{
    public string str;
}

?

本文摘自 :https://blog.51cto.com/u

開通會員,享受整站包年服務立即開通 >