2-最新2021C#.NET5--语法之反射_哔哩哔哩_bilibili
一、什么是反射和dll文件加载
1、反射是操作dll文件的一个类库
-
反射需要引用包:using System.Reflection;
2、dll文件什么?在项目文件的\bin\Debug\net6.0目录下
二、反射的基本使用
1、加载DLL文件
找到dll文件
通过Reflection反射类库中的方法来操作dll文件
-
方案一代码 Load:从ReflectionTest项目中,读取Test项目的dll文件,在ReflectionTest项目中对Test项目添加引用
-
方案二代码 LoadFile
-
方案三代码 LoadFrom
二、通过反射调用构造方法
1、在Test项目中创建一个测试类Person
namespace Test
{
public class Person
{
public Person()
{
Console.WriteLine("这里是Test项目中,Person类的,无参构造函数");
}
public Person(string value1)
{
Console.WriteLine($"这里是Test项目中,Person类的,有参构造函数,参数是:{value1}");
}
public Person(string value1,string value2)
{
Console.WriteLine($"这里是Test项目中,Person类的,有参构造函数,参数是:{value1} 和 {value2}");
}
public int Id { get; set; }
public string Name { get; set; }
}
}
2、在ReflectionTest项目中,通过反射,实例化Test项目中的Person类
using System.Reflection;
namespace ReflectionTest
{
public class Program
{
public static void Main()
{
// --1、加载DLL文件
Assembly assembly = Assembly.LoadFrom(
@"C:\\Users\\Raoli\\Desktop\\T" +
@"est\\Test\\Test\\bin\\Debug\\net6.0\\Test.dll");
// --2、获取DLL文件中的某个具体类型,即Test项目中的Person类型
Type type = assembly.GetType("Test.Person");
// --3、实例化
object objTest1 = Activator.CreateInstance(type); // 动态实例化,调用Person的 无 参构造函数
object objTest2 = Activator.CreateInstance(type, new object[] { "测试1" }); // 动态实例化,调用Person的 1个参数的,有 参构造函数
object objTest3 = Activator.CreateInstance(type, new object[] { "测试1","测试2" }); // 动态实例化,调用Person的 2个参数的,有 参构造函数
}
}
}
三、调用私有构造方法
1、Test项目(被调用的dll文件)代码
namespace Test
{
public class Person
{
private Person()
{
Console.WriteLine("这里是Test项目中,Person类的,私有 无参构造函数");
}
public int Id { get; set; }
public string Name { get; set; }
}
}
2、通过反射调用Person的私有构造函数
-
关键就是true这个参数
d
四、获取调用的dll文件中所有的类:GetTypes()
1、dll文件中有Student和Person类
using System.Reflection;
namespace ReflectionTest
{
public class Program
{
public static void Main()
{
// --1、加载DLL文件
Assembly assembly = Assembly.LoadFrom(
@"C:\\Users\\Raoli\\Desktop\\T" +
@"est\\Test\\Test\\bin\\Debug\\net6.0\\Test.dll");
// --2、获取dll文件中的所有类
foreach (var item in assembly.GetTypes())
{
Console.WriteLine(item);
}
}
}
}
五、获取某个具体类的所有构造参数信息
using System.Reflection;
namespace ReflectionTest
{
public class Program
{
public static void Main()
{
// --1、加载DLL文件
Assembly assembly = Assembly.LoadFrom(
@"C:\\Users\\Raoli\\Desktop\\T" +
@"est\\Test\\Test\\bin\\Debug\\net6.0\\Test.dll");
// --2、获取DLL文件中的某个具体类型,即Test项目中的Person类型
Type type = assembly.GetType("Test.Person");
// --3、获取Person类的所有构造方法
foreach (var ctor in type.GetConstructors())
{
Console.WriteLine($"构造方法:{ctor.Name}");
// -4、获取构造方法的所有参数
foreach (var param in ctor.GetParameters())
{
Console.WriteLine($"构造方法的参数:{param.Name},参数类型{param.ParameterType}");
}
}
}
}
}
六、调用泛型方法和普通方法
1、Test项目中Person类的代码
namespace Test
{
public class Person
{
// 非泛型无参方法
public void Show1()
{
Console.WriteLine("非泛型无参方法");
}
// 非泛型有参方法
public void Show2(int id ,string name)
{
Console.WriteLine($"非泛型有参方法,id:{id},name:{name}");
}
// 无参泛型方法
public void Show3<T>()
{
Console.WriteLine("无参泛型方法");
}
// 有参泛型方法
public void Show4<T>(int id,string name)
{
Console.WriteLine($"有参泛型方法,id:{id},name:{name}");
}
}
}
2、调用Person类的泛型方法和普通方法
using System.Reflection;
namespace ReflectionTest
{
public class Program
{
public static void Main()
{
// --1、加载DLL文件
Assembly assembly = Assembly.LoadFrom(
@"C:\\Users\\Raoli\\Desktop\\T" +
@"est\\Test\\Test\\bin\\Debug\\net6.0\\Test.dll");
// --2、获取DLL文件中的某个具体类型,即Test项目中的Person类型
Type type = assembly.GetType("Test.Person");
// --3、创建实例
object obj = Activator.CreateInstance(type,true);
// --4、调用 无参泛型方法
var method = type.GetMethod("Show3"); // 查找指定方法
var genericMethod = method.MakeGenericMethod(new Type[] {typeof(int)}); // 指定泛型参数类型T
genericMethod.Invoke(obj, new object[] { });
// --5、调用 有参泛型方法
var method1 = type.GetMethod("Show4"); // 查找指定方法
var genericMethod1 = method1.MakeGenericMethod(new Type[] { typeof(int) }); // 指定泛型参数类型T
genericMethod1.Invoke(obj, new object[] {1,"test"});
// --6、调用 无参非泛型方法
var method2 = type.GetMethod("Show1"); // 查找指定方法
method2.Invoke(obj, new object[] {});
// --6、调用 有参非泛型方法
var method3 = type.GetMethod("Show2"); // 查找指定方法
method3.Invoke(obj, new object[] { 2, "ttt" });
}
}
}
七、创建泛型类+调用泛型方法
1、查看泛型方法实际上对应的方法可知:类名命名考虑到了有几个泛型参数,如下图中有两个泛型参数,类的命名后面就带有2,那么通过反射调用的时候就要完整的写上类名,即加上
2
2、泛型调用
using System.Reflection;
namespace ReflectionTest
{
public class Program
{
public static void Main()
{
// --1、加载DLL文件
Assembly assembly = Assembly.LoadFrom(
@"C:\\Users\\Raoli\\Desktop\\T" +
@"est\\Test\\Test\\bin\\Debug\\net6.0\\Test.dll");
// --2、获取指定类型
Type type = assembly.GetType("Test.GenericClass`2").MakeGenericType(typeof(int), typeof(string));
// --3、实例化
object obj = Activator.CreateInstance(type);
// --4、调用泛型方法
var method = type.GetMethod("GenericMethod").MakeGenericMethod(typeof(int));
method.Invoke(obj, new object[] { });
}
}
}
八、设置属性的值和获取属性的值
using System.Reflection;
namespace ReflectionTest
{
public class Program
{
public static void Main()
{
// --1、加载DLL文件
Assembly assembly = Assembly.LoadFrom(
@"C:\\Users\\Raoli\\Desktop\\T" +
@"est\\Test\\Test\\bin\\Debug\\net6.0\\Test.dll");
// --2、获取指定类型
Type type = assembly.GetType("Test.Student");
// --3、实例化
object obj = Activator.CreateInstance(type);
// --4、获取所有属性,并给 某个实例化对象 属性设置值
foreach (var prop in type.GetProperties())
{
if (prop.Name.Equals("Name"))
{
prop.SetValue(obj, "张三");
}
if (prop.Name.Equals("Id"))
{
prop.SetValue(obj, 1);
}
}
// --5、获取 某个实例化对象的 属性值
foreach (var prop in type.GetProperties())
{
Console.WriteLine(prop.GetValue(obj));
}
}
}
}
九、调用私有方法
using System.Reflection;
namespace ReflectionTest
{
public class Program
{
public static void Main()
{
// --1、加载DLL文件
Assembly assembly = Assembly.LoadFrom(
@"C:\\Users\\Raoli\\Desktop\\T" +
@"est\\Test\\Test\\bin\\Debug\\net6.0\\Test.dll");
// --2、获取指定类型
Type type = assembly.GetType("Test.Student");
// --3、实例化
object obj = Activator.CreateInstance(type);
// --4、调用私有方法
var method = type.GetMethod("PrivateMethod",BindingFlags.Instance | BindingFlags.NonPublic); // 找到私有方法
method.Invoke(obj,null);
}
}
}