• C#的反射Reflection


    1作用

    1. 操作dll文件的一个类库。【实例化dll里的class对象】
    2. dll文件是由 .net创建的【类库项目】生成的。

    2命名空间

    using System.Reflection;

    3加载dll文件

    1. // 加载方法1:
    2. // 【缺点】需要吧dll文件复制到Debug文件下。
    3. // C#环境的dll可以在,项目》引用》添加引用》。。 到项目中
    4. Assembly assembly1 = Assembly.Load("Help_USB_CAN");//文件Help_USB_CAN.dll
    5. // 加载方法2:
    6. Assembly assembly2 = Assembly.LoadFile(@"D:\app\Help_USB_CAN.dll");//文件完整路径
    7. // 加载方法3:
    8. Assembly assembly3 = Assembly.LoadFrom(@"Help_USB_CAN.dll");//包含 1 2 写法
    9. Assembly assembly4 = Assembly.LoadFrom(@"D:\app\Help_USB_CAN.dll");//包含 1 2 写法

    4获取class类型

    1. " 在dll文件内获取class类型"
    2. Type class_Type = assembly4.GetType("命名空间名.class类名"); // namespace.class
    3. " 在dll文件内获取 所有class类型"
    4. Type[] all_class_Type = assembly4.GetTypes(); // namespace.class

    5类型实例化class

     Activator.CreateInstance(class_Type);        // 构造方法激活器。创建实例

    1. // 实例化class
    2. //RedlectionTest obj = new RedlectionTest();// 这种是知道具体类型
    3. " 创建类的实例" 【构造方法激活器。创建实例】 默认public构造方法
    4. object 风韵犹存的少妇 = Activator.CreateInstance(class_Type);// 创建的是class【构造方法】
    5. // 创建其他的有参构造 数组构造方法,带1个参数
    6. object 风韵犹存的少妇2 = Activator.CreateInstance(class_Type,new object[]{"带一个参数的构造方法","数组第2个对象的构造方法"});// 创建的是class【构造方法】
    7. // 私有构造方法 私有构造方法
    8. object 风韵犹存的少妇3 = Activator.CreateInstance(class_Type,True);//创建的是class【构造方法】
    9. static void Main(string[] args)
    10. {
    11. " 加载外部DLL" 【集合。加载】
    12. Assembly assembly = Assembly.LoadFrom("External.dll");
    13. " 获取DLL中的类" 【集合。获取类型】
    14. Type type = assembly.GetType("External.ExternalClass");
    15. " 创建类的实例化" 【激活器。方法】
    16. object instance = Activator.CreateInstance(type);
    17. " 调用类中的方法" 【类型Get方法】
    18. MethodInfo method = type.GetMethod("ExternalMethod");
    19. method.Invoke(instance, null);
    20. }

    这里获取到了class类型 。      风韵犹存的少妇3的class类型

    Get所有构造方法

    .GetConstructors(BindingFlags.Instance|BindingFlags.NonPublic||BindingFlags.Public))

    Get私有方法

    .GetMethod("私有方法名字",BindingFlags.Instance|BindingFlags.NonPublic)

    Get参数

    .GetParameters();

    6获取所有class类型

    【所有class类型】【所有class构造方法类型】 【所有构造方法参数类型

    1. foreach( var class_Type in assembly4.GetTypes()) // 所有class类型
    2. {
    3. Console.WriteLine(class_Type.Name); // class类型名
    4. }
    5. "class所有的构造方法"
    6. class.GetConstructors();
    7. foreach( var class_构造 in class_Type.GetConstructors(【标签】)) // 所有class类型
    8. {
    9. Console.WriteLine(class_构造.Name); // class所有构造方法
    10. }
    11. //========================
    12. 【标签】 实例化的,私有的,公有的
    13. BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public
    14. //========================
    15. "构造方法的所有参数类型"
    16. class_构造.GetParameters();
    17. foreach( var param in class_构造.GetParameters()) // 所有class类型
    18. {
    19. Console.WriteLine(param.ParameterType); // 构造方法的 参数
    20. }
    21. //==============================
    22. 方法A 方法a = 风韵犹存的少妇3 as 方法A; 裁剪出方法

     7调用私有方法

    1. 私有方法
    2. // 私有构造方法 私有构造方法
    3. object 风韵犹存的少妇3 = Activator.CreateInstance(class_Type,True);//创建的是class【构造方法】
    4. //========================
    5. 【标签】 实例化的,私有的,公有的
    6. BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public
    7. //========================
    8. var 方法a = class_Type.GetMethod("方法A",【标签】);
    9. 方法a.Invoke(风韵犹存的少妇3,new object[]{});

    8实例化对象  s们  class

     "在dll文件里获取类型"并且"实例化"

    1. //=================================
    2. " 在dll文件内获取class类型"
    3. Type class_Type = assembly4.GetType("命名空间名.class类名"); // namespace.class
    4. foreach( var item in assembly4.GetTypes()) // 所有class对象
    5. {
    6. Console.WriteLine(item.Name); // class 对象名
    7. }
    8. // 所有构造方法
    9. foreach( var item in class_Type.GetConstructors(BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public)) // 所有class对象【实例,私有,公开】
    10. {
    11. Console.WriteLine(item.Name); // 所有class对象
    12. foreach( var param in item.GetParameters()) // 对象.all参数【所有参数】
    13. {
    14. Console.WriteLine(param.ParameterType); // 对象.参数类型
    15. }
    16. }

    1. using System;
    2. using System.Reflection;
    3. public class MyClass
    4. {
    5. public void MyMethod(int x)
    6. {
    7. Console.WriteLine(x);
    8. }
    9. }
    10. class Program
    11. {
    12. static void Main(string[] args)
    13. {
    14. // 获取MyClass类型的Type对象
    15. Type myType = typeof(MyClass);
    16. // 创建MyClass的实例 【激活器。方法】
    17. object obj = Activator.CreateInstance(myType);
    18. // 获取MyMethod方法的MethodInfo对象 【方法信息】
    19. MethodInfo myMethod = myType.GetMethod("MyMethod");
    20. // 调用MyMethod方法
    21. myMethod.Invoke(obj, new object[] { 123 });
    22. }
    23. }
    1. 这个Demo首先定义了一个MyClass类,其中包含一个MyMethod方法。
    2. 然后在Main方法中,
    3. 通过typeof获取MyClass类型的Type对象,
    4. 再通过Activator.CreateInstance创建MyClass的实例。
    5. 接着,通过Type.GetMethod获取MyMethod方法的MethodInfo对象,
    6. 最后通过MethodInfo.Invoke调用MyMethod方法并传入参数。

    2dll文件

    1. using System;
    2. using System.Reflection;
    3. namespace ReflectionDemo
    4. {
    5. class Program
    6. {
    7. static void Main(string[] args)
    8. {
    9. " 加载外部DLL" 【集合。加载】
    10. Assembly assembly = Assembly.LoadFrom("External.dll");
    11. " 获取DLL中的类" 【集合。获取类型】
    12. Type type = assembly.GetType("External.ExternalClass");
    13. " 创建类的实例" 【激活器。方法】
    14. object instance = Activator.CreateInstance(type);
    15. " 调用类中的方法" 【类型Get方法】
    16. MethodInfo method = type.GetMethod("ExternalMethod");
    17. method.Invoke(instance, null);
    18. }
    19. }
    20. }
    1. 上述代码中,我们首先使用Assembly.LoadFrom方法加载外部DLL文件,
    2. 然后使用GetType方法获取DLL中的类,
    3. 接着使用Activator.CreateInstance方法创建类的实例,
    4. 最后使用GetMethod方法获取类中的方法并使用Invoke方法调用该方法。

    C#反射是一种强大的机制,它允许程序在运行时获取类型信息并动态地创建类型实例、访问成员、调用方法等。下面是C#反射的详细介绍:

    1. 反射的基本概念

    C#反射是指在程序运行时动态地获取类型信息并进行操作的机制。在C#中,每个类型都有一个对应的Type对象,通过这个对象可以获取类型的名称、命名空间、基类、实现的接口、字段、属性、方法等信息。反射的核心是Type类,它提供了一系列方法和属性,用于获取类型信息和操作类型。

    2. 反射的基本用法

    (1)获取类型信息

    在C#中,可以使用typeof运算符或GetType方法获取类型的Type对象。例如:

    ```csharp
    Type type1 = typeof(string); // 获取string类型的Type对象
    Type type2 = "hello".GetType(); // 获取字符串"hello"的Type对象
    ```

    (2)创建类型实例

    可以使用Activator类的CreateInstance方法创建类型的实例。例如:

    ```csharp
    Type type = typeof(MyClass); // 获取MyClass类型的Type对象
    object obj = Activator.CreateInstance(type); // 创建MyClass类型的实例
    ```

    (3)访问成员

    可以使用Type类的GetField、GetProperty、GetMethod等方法获取类型的字段、属性、方法等成员信息,并使用反射调用这些成员。例如:

    ```csharp
    Type type = typeof(MyClass); // 获取MyClass类型的Type对象
    object obj = Activator.CreateInstance(type); // 创建MyClass类型的实例
    FieldInfo field = type.GetField("myField"); // 获取名为myField的字段
    field.SetValue(obj, 123); // 设置myField的值为123
    int value = (int)field.GetValue(obj); // 获取myField的值
    ```

    (4)调用方法

    可以使用MethodInfo类的Invoke方法调用类型的方法。例如:

    ```csharp
    Type type = typeof(MyClass); // 获取MyClass类型的Type对象
    object obj = Activator.CreateInstance(type); // 创建MyClass类型的实例
    MethodInfo method = type.GetMethod("MyMethod"); // 获取名为MyMethod的方法
    method.Invoke(obj, new object[] { 123 }); // 调用MyMethod方法,并传入参数123
    ```

    3. 反射的优缺点

    反射的优点是可以在运行时动态地获取类型信息并进行操作,使程序更加灵活和可扩展。反射的缺点是性能较差,因为反射需要在运行时进行类型检查和成员访问,而这些操作都比较耗时。因此,在需要高性能的场合,应该尽量避免使用反射。

    作用:用于查看别人写的  lookme.exe程序内有些什么

    【1】准备材料:

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Threading.Tasks;
    6. namespace lookme
    7. {
    8. public class me
    9. {
    10. int ziduan;
    11. int ziduan2 = 66;
    12. int 字段;
    13. int 字段2 = 77;
    14. public int shuxing { get; set; }
    15. public int shuxing2 { get; set; } = 77;
    16. public int 属性 { get; set; }
    17. public int 属性2 { get; set; } = 88;
    18. void fun()
    19. {
    20. int i = 0;
    21. i += 1;
    22. }
    23. public int fun2()
    24. {
    25. ++ziduan;
    26. return ziduan;
    27. //++i;
    28. //return i;
    29. }
    30. void 方法()
    31. {
    32. int i=0;
    33. i+=1;
    34. }
    35. public void 方法2()
    36. {
    37. int i = 0;
    38. i += 1;
    39. }
    40. }
    41. }

    就是个普通窗体,加个me的类。 

     运行后会生成   exe文件

    你把它复制出来。一会要用到它。

    名称长格式:就是完全限定名。

    【1】另外新建工程,引入反射的命名空间

    1. //【1】引入反射的命名空间
    2. using System.Reflection;// 反射

    【2】加载程序集(加载      exe文件)

    有3种加载模式:1加载exe程序(exe需要复制到当前 \bin\Debug  文件夹下)

                                2加载exe程序的文件夹路径(这个比较好)

                                3加载exe程序的程序集名称

    1. Assembly ass1 = Assembly.LoadFrom("登录窗.exe");//需要将登录窗.exe文件复制到\bin\Debug文件下
    2. Assembly ass2 = Assembly.LoadFile(System.IO.Directory.GetCurrentDirectory() + "\\InterfaceAndPolymorphism.exe");// 文件路径
    3. Assembly ass3 = Assembly.Load("InterfaceAndPolymorphism");//程序集名称

    用文件路径加载 .exe程序 比较好 

    1. // 加载exe文件路径
    2. try
    3. {
    4. //Assembly ass1 = Assembly.LoadFrom(assName);//需要将登录窗.exe文件复制到\bin\Debug文件下
    5. Assembly ass2 = Assembly.LoadFile(@"C:\Users\Administrator\Desktop\lookme\lookme\lookme\bin\Debug\lookme.exe");
    6. //Assembly ass3 = Assembly.Load("InterfaceAndPolymorphism");//程序集名称
    7. if (ass2 == null) throw new Exception();
    8. return ass2;
    9. }
    10. catch (Exception ex)
    11. {
    12. MessageBox.Show(ex.Message);
    13. throw ex;
    14. }//显示错误

    这里不报错,不为空,说明  .exe 程序已经加载到你的项目里了。 

     【3】获取新建对象

    .exe程序加载进来后,就可以取出它里面的成员了。

     1先查看里面有什么

    1. Type[] types = ass2.GetTypes();
    2. foreach (var item in types)
    3. {
    4. //item.Name:类的名称
    5. //item:类的完全限定名(命名空间+类名)
    6. Console.WriteLine(item.Name + "\t\t" + item);
    7. }

    Form1是子窗体名称,me是我自己建的类。

     比如我想新建出 me 这个类,要用完全限定名。命名空间+类

    object obj= ass2.CreateInstance("lookme.me");

    这里 obj 已经能看到 me的属性了。需要想办法把 obj 强制转成 me 这个类。 一般用接口,就是me继承xxx接口,你另外的过程也有xxx接口,这样把me强制成接口

    return (接口)Assembly.Load(程序集名称).CreateInstance(对象名称);//完全限定名
    1. 5. 反射调用普通方法步骤
    2. 1. 动态加载DLL Assembly assembly=Assembly.LoadFrom(@"DLL路径");
    3. 2. 获取对象类型 Type type=assembly.GetType("对象名")
    4. 3. 创建对象实例 Object otest=Activator.CreateInstance(类型);
    5. 4. 获取方法 MethodInfo show1=type.GetMethod("show2")
    6. 5. Invoke方法(如果方法有参数,传递参数类型必须和方法一致) show1.Invoke(otest,new object[]{123}); show2.Invoke(otest,new object[0]);
    7. 6. 如果调用的是重载方法在第四步获取方法时要写对方法参数类型和参数数目(好像也有封装好可以不写具体参数,直接在调用时写明即可)

    【2】准备查看   exe内的成员:

    另外新建一个工程,你把它复制到工程的相对路径。也在Debug文件下,lookme复制进去

     

     

    这段程序就是加载exe文件,这样就可以剖腹看看里面有些什么:

    这里就扒出了 me 这个类内, 属性,方法了

    1. 以下是一个C#反射的入门Demo,它可以通过反射获取类的信息并调用其中的方法:
    2. using System;
    3. using System.Reflection;
    4. public class MyClass
    5. {
    6. public void MyMethod(int x)
    7. {
    8. Console.WriteLine(x);
    9. }
    10. }
    11. class Program
    12. {
    13. static void Main(string[] args)
    14. {
    15. // 获取MyClass类型的Type对象
    16. Type myType = typeof(MyClass);
    17. // 创建MyClass的实例
    18. object obj = Activator.CreateInstance(myType);
    19. // 获取MyMethod方法的MethodInfo对象
    20. MethodInfo myMethod = myType.GetMethod("MyMethod");
    21. // 调用MyMethod方法
    22. myMethod.Invoke(obj, new object[] { 123 });
    23. }
    24. }
    25. 这个Demo首先定义了一个MyClass类,其中包含一个MyMethod方法。然后在Main方法中,通过typeof获取MyClass类型的Type对象,再通过Activator.CreateInstance创建MyClass的实例。接着,通过Type.GetMethod获取MyMethod方法的MethodInfo对象,最后通过MethodInfo.Invoke调用MyMethod方法并传入参数。
    26. dll文件,用C#写个反射demo
    27. 以下是一个使用C#反射技术动态加载外部DLL并调用其中方法的示例代码:
    28. using System;
    29. using System.Reflection;
    30. namespace ReflectionDemo
    31. {
    32. class Program
    33. {
    34. static void Main(string[] args)
    35. {
    36. // 加载外部DLL
    37. Assembly assembly = Assembly.LoadFrom("External.dll");
    38. // 获取DLL中的类
    39. Type type = assembly.GetType("External.ExternalClass");
    40. // 创建类的实例
    41. object instance = Activator.CreateInstance(type);
    42. // 调用类中的方法
    43. MethodInfo method = type.GetMethod("ExternalMethod");
    44. method.Invoke(instance, null);
    45. }
    46. }
    47. }
    48. 上述代码中,我们首先使用Assembly.LoadFrom方法加载外部DLL文件,然后使用GetType方法获取DLL中的类,接着使用Activator.CreateInstance方法创建类的实例,最后使用GetMethod方法获取类中的方法并使用Invoke方法调用该方法。
    49. 详细讲下C#反射
    50. C#反射是一种强大的机制,它允许程序在运行时获取类型信息并动态地创建类型实例、访问成员、调用方法等。下面是C#反射的详细介绍:
    51. 反射的基本概念
    52. C#反射是指在程序运行时动态地获取类型信息并进行操作的机制。在C#中,每个类型都有一个对应的Type对象,通过这个对象可以获取类型的名称、命名空间、基类、实现的接口、字段、属性、方法等信息。反射的核心是Type类,它提供了一系列方法和属性,用于获取类型信息和操作类型。
    53. 反射的基本用法
    54. 1)获取类型信息
    55. 在C#中,可以使用typeof运算符或GetType方法获取类型的Type对象。例如:
    56. Type type1 = typeof(string); // 获取string类型的Type对象
    57. Type type2 = "hello".GetType(); // 获取字符串"hello"的Type对象
    58. 2)创建类型实例
    59. 可以使用Activator类的CreateInstance方法创建类型的实例。例如:
    60. Type type = typeof(MyClass); // 获取MyClass类型的Type对象
    61. object obj = Activator.CreateInstance(type); // 创建MyClass类型的实例
    62. 3)访问成员
    63. 可以使用Type类的GetField、GetProperty、GetMethod等方法获取类型的字段、属性、方法等成员信息,并使用反射调用这些成员。例如:
    64. Type type = typeof(MyClass); // 获取MyClass类型的Type对象
    65. object obj = Activator.CreateInstance(type); // 创建MyClass类型的实例
    66. FieldInfo field = type.GetField("myField"); // 获取名为myField的字段
    67. field.SetValue(obj, 123); // 设置myField的值为123
    68. int value = (int)field.GetValue(obj); // 获取myField的值
    69. 4)调用方法
    70. 可以使用MethodInfo类的Invoke方法调用类型的方法。例如:
    71. Type type = typeof(MyClass); // 获取MyClass类型的Type对象
    72. object obj = Activator.CreateInstance(type); // 创建MyClass类型的实例
    73. MethodInfo method = type.GetMethod("MyMethod"); // 获取名为MyMethod的方法
    74. method.Invoke(obj, new object[] { 123 }); // 调用MyMethod方法,并传入参数123
    75. 反射的优缺点
    76. 反射的优点是可以在运行时动态地获取类型信息并进行操作,使程序更加灵活和可扩展。反射的缺点是性能较差,因为反射需要在运行时进行类型检查和成员访问,而这些操作都比较耗时。因此,在需要高性能的场合,应该尽量避免使用反射。

  • 相关阅读:
    点云学习笔记14——ModuleNotFoundError: No module named ‘rospy
    Java实习生常规技术面试题每日十题Java基础(六)
    hadoop集群搭建
    linux基础
    23种设计模式-单例设计模式介绍带实战
    前端页面设计 | 博客系统
    Qt 5.12.12 静态编译(MinGW)
    IMX6Q的SD卡启动使用教程【超完整】(2):busybox交叉编译根文件系统
    云计算革命:多云管理与混合云的实践指南
    微软放弃“封禁”商业开源!
  • 原文地址:https://blog.csdn.net/cfqq1989/article/details/127725508