C#中的反射原理及应用
生活随笔
收集整理的這篇文章主要介紹了
C#中的反射原理及应用
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
先來看一張圖片
逆向工程,可以把Dll/Exe文件反編譯回來,IL是對標于C#代碼的代碼,metadata是一個清單數(shù)據(jù),記錄里面包含什么而不是細節(jié)的具體實現(xiàn);
1.反射的原理:
反射是System.Reflection命名空間,可以讀取metadata,并使用metadata,是微軟提供的一個幫助類,在各個場景中都會使用到,而其主要作用是“解耦”,降低對細節(jié)的依賴。
簡單的理解就是,當C#代碼在編譯的時候,會將工程里面的類及其方法記錄在metadata里面,然后利用System.reflection可以讀取metadata記錄的信息,從而就可以根據(jù)類型的實例拿到對應(yīng)的類型和所有的類方法。
接下來是應(yīng)用,看如下代碼
場景1
通過獲得一個實例的Type,然后利用這個Type去生成一個新得實例
namespace ConsoleApp1 {class Class1{public void Fun(int a, int b){int res = a + b;Console.WriteLine($"Fun res is {res}");}public int val = 10;}static void Main(string[] args){Class1 class_a = new Class1();Type a_type = class_a.GetType();dynamic aa = Activator.CreateInstance(a_type); // 根據(jù)一類類型動態(tài)創(chuàng)建一個新類實例Console.WriteLine(aa.GetType()); // 輸出的結(jié)果是ConsoleApp1.Class1Console.WriteLine(aa.val); // 10}}場景2
創(chuàng)建dll中的實例,這里為了方便,將上述工程生成解決方案,在其bin目錄下就會有對應(yīng)的dll文件,代碼如下:
static void Main(string[] args){//這里的絕對路徑,找到你之前生成的dll文件Assembly assembly = Assembly.LoadFrom("E:/study_file/Pracfile/CStest1/ConsoleApp1/bin/Debug/netcoreapp3.1/ConsoleApp1.dll");Type cur_type = assembly.GetType("ConsoleApp1.Class1");dynamic cur_obj = Activator.CreateInstance(cur_type);Console.WriteLine($"res is : {cur_obj.GetType()}"); // res is : ConsoleApp1.Class1}在這里是生成根據(jù)拿到的類型,生成實例的兩個例子,下面介紹下獲取對應(yīng)類型方法及其調(diào)用的方式。代碼如下:
namespace ConsoleApp1 {class Class1{public void Fun(int a, int b){int res = a + b;Console.WriteLine($"a = {a} b = {b}");}public void Fun(int a, int b, int c) // 重載{int res = a + b;Console.WriteLine($"a = {a} b = {b} c = {c}");}public int val = 10;}static void Main(string[] args){Assembly assembly = Assembly.LoadFrom("E:/study_file/Pracfile/CStest1/ConsoleApp1/bin/Debug/netcoreapp3.1/ConsoleApp1.dll");//這里的絕對路徑,找到你之前生成的dll文件Type cur_type = assembly.GetType("ConsoleApp1.Class1");dynamic cur_obj = Activator.CreateInstance(cur_type);// 生成個實例// 根據(jù)函數(shù)名字,以及參數(shù)列表Type類型獲取對應(yīng)的函數(shù),獲取保存在metadata中的數(shù)據(jù)信息MethodInfo methodInfo_a = cur_type.GetMethod("Fun",new Type[] { typeof(int), typeof(int)}); methodInfo_a?.Invoke(cur_obj, new object[] { 3, 5 });MethodInfo methodInfo_b = cur_type.GetMethod("Fun", new Type[] { typeof(int), typeof(int), typeof(int) });methodInfo_b?.Invoke(cur_obj, new object[] { 3, 5, 7 }); // 調(diào)用對應(yīng)的函數(shù)} }還有一些常用的函數(shù)接口,也簡單的記錄下
namespace ConsoleApp1 {class Class1{private void Test(){Console.WriteLine($"this is pricate Test !!!");}public void Fun(int a, int b){int res = a + b;Console.WriteLine($"a = {a} b = {b}");}public void Fun(int a, int b, int c){int res = a + b;Console.WriteLine($"a = {a} b = {b} c = {c}");}public int val = 10;}class Program{static void Main(string[] args){Assembly assembly = Assembly.LoadFrom("E:/study_file/Pracfile/CStest1/ConsoleApp1/bin/Debug/netcoreapp3.1/ConsoleApp1.dll");//這里的絕對路徑,找到你之前生成的dll文件Type cur_type = assembly.GetType("ConsoleApp1.Class1");dynamic cur_obj = Activator.CreateInstance(cur_type);//獲取所有的函數(shù)列表MethodInfo[] methodInfos = cur_type.GetMethods(); foreach(MethodInfo m in methodInfos){}//獲取單個函數(shù)MethodInfo methodInfo_a = cur_type.GetMethod("Fun", new Type[] { typeof(int), typeof(int), typeof(int) });methodInfo_a?.Invoke(cur_obj, new object[] { 1,2,3});//用 BindingFlags標記拿到的函數(shù)范圍 這里表示的范圍是實例中的非公有函數(shù)(private protect internal)MethodInfo methodInfo_b = cur_type.GetMethod("Test", BindingFlags.Instance | BindingFlags.NonPublic);methodInfo_b?.Invoke(cur_obj, null); // this is pricate Test !!!這里能直接調(diào)用私有函數(shù),是不是很神奇}}}參考文檔
總結(jié)
以上是生活随笔為你收集整理的C#中的反射原理及应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智慧船舶,在青春的赛道上奋力奔跑
- 下一篇: Django 分页模块