C#中的反射原理及应用
生活随笔
收集整理的這篇文章主要介紹了
C#中的反射原理及应用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
先來看一張圖片
逆向工程,可以把Dll/Exe文件反編譯回來,IL是對標于C#代碼的代碼,metadata是一個清單數據,記錄里面包含什么而不是細節的具體實現;
1.反射的原理:
反射是System.Reflection命名空間,可以讀取metadata,并使用metadata,是微軟提供的一個幫助類,在各個場景中都會使用到,而其主要作用是“解耦”,降低對細節的依賴。
簡單的理解就是,當C#代碼在編譯的時候,會將工程里面的類及其方法記錄在metadata里面,然后利用System.reflection可以讀取metadata記錄的信息,從而就可以根據類型的實例拿到對應的類型和所有的類方法。
接下來是應用,看如下代碼
場景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); // 根據一類類型動態創建一個新類實例Console.WriteLine(aa.GetType()); // 輸出的結果是ConsoleApp1.Class1Console.WriteLine(aa.val); // 10}}場景2
創建dll中的實例,這里為了方便,將上述工程生成解決方案,在其bin目錄下就會有對應的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}在這里是生成根據拿到的類型,生成實例的兩個例子,下面介紹下獲取對應類型方法及其調用的方式。代碼如下:
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);// 生成個實例// 根據函數名字,以及參數列表Type類型獲取對應的函數,獲取保存在metadata中的數據信息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 }); // 調用對應的函數} }還有一些常用的函數接口,也簡單的記錄下
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);//獲取所有的函數列表MethodInfo[] methodInfos = cur_type.GetMethods(); foreach(MethodInfo m in methodInfos){}//獲取單個函數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標記拿到的函數范圍 這里表示的范圍是實例中的非公有函數(private protect internal)MethodInfo methodInfo_b = cur_type.GetMethod("Test", BindingFlags.Instance | BindingFlags.NonPublic);methodInfo_b?.Invoke(cur_obj, null); // this is pricate Test !!!這里能直接調用私有函數,是不是很神奇}}}參考文檔
總結
以上是生活随笔為你收集整理的C#中的反射原理及应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智慧船舶,在青春的赛道上奋力奔跑
- 下一篇: C# 平方、开方、保留小数 运算