先来看一张图片
简单的理解就是,当C#代码在编译的时候,会将工程里面的类及其方法记录在metadata里面,然后利用System.reflection可以读取metadata记录的信息,从而就可以根据类型的实例拿到对应的类型和所有的类方法。
接下来是应用,看如下代码
通过获得一个实例的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.Class1
Console.WriteLine(aa.val); // 10
}
}
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 !!!这里能直接调用私有函数,是不是很神奇
}
}
}
因篇幅问题不能全部显示,请点此查看更多更全内容