Reflection反射【C#】

作用

第2章8节,50分

接口可以实现多态:实例子类赋值给父类接口,这样,同样的接口能实现不同的功能。

 让其他同事去写程序,写好后,把dll文件复制给你。由于是继承同样的接口,同事的实例对象可以赋值给你的接口使用。

反射的作用是:加载dll文件,new出里面的实例对象

                        拿到实例对象,就能赋值给接口使用,实现多态。

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

1命名空间

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

2加载dll文件

主要使用 .Load  方法 

Assembly assembly2 = Assembly.LoadFile(@"D:\app\Help_USB_CAN.dll");//文件完整路径

// 加载方法1:
// 【缺点】需要吧dll文件复制到Debug文件下。
//    C#环境的dll可以在,项目》引用》添加引用》。。 到项目中
Assembly assembly1 = Assembly.Load("Help_USB_CAN");//文件Help_USB_CAN.dll

// 加载方法2:
Assembly assembly2 = Assembly.LoadFile(@"D:\app\Help_USB_CAN.dll");//文件完整路径

// 加载方法3:
Assembly assembly3 = Assembly.LoadFrom(@"Help_USB_CAN.dll");//包含 1 2 写法

Assembly assembly4 = Assembly.LoadFrom(@"D:\app\Help_USB_CAN.dll");//包含 1 2 写法

3所有成员

            Assembly ass1 = Assembly.Load("InterfaceAndPolymorphism");

            Assembly ass2 = Assembly.LoadFile(System.IO.Directory.GetCurrentDirectory() + "\\InterfaceAndPolymorphism.exe");

            Assembly ass3 = Assembly.LoadFrom("InterfaceAndPolymorphism.exe");

            //观察程序集给我们的信息
            Type[] types = ass1.GetTypes();
            foreach (var item in types)
            {
                //item.Name:类的名称
                //item:类的完全限定名(命名空间+类名)
                Console.WriteLine(item.Name + "\t\t" + item);
            }
            //我们从一个程序集中,能够找到所有的类型(类类型、接口类型、泛型类型......)

            Console.WriteLine("=========================================");

 Type teacherType = ass1.GetType("xiketang.com4.Teacher"); //这个字符串严格区分大小写

 //这个Type就是包括了一个类型的所有成员快照

 //我们通过一个对象的类型,可以找到类的所有成员,比如我找Teacher的所有属性
 PropertyInfo[] properties = teacherType.GetProperties();
 //这些在我们后面自己开发ORM框架时候,非常有用。

 Teacher teacher1 = (Teacher)Activator.CreateInstance(teacherType);

 //  使用指定类型的默认构造函数来创建该类型的实例。
 // public static object CreateInstance(Type type);

 Teacher teacher2 = (Teacher)ass1.CreateInstance("xiketang.com4.Teacher");

 //上面的内容合并写
 Teacher teacher3 = (Teacher)Assembly.Load("InterfaceAndPolymorphism").CreateInstance("xiketang.com4.Teacher");

 //通过构造方法创建对象(下面请大家记住方法)
 object object1 = Activator.CreateInstance(teacherType, new object[] { "常老师" });
 object object2 = Activator.CreateInstance(teacherType, new object[] { "常老师", "130000000000000" });

 

4获取class类型

" 在dll文件内获取class类型"
Type  class_Type = assembly4.GetType("命名空间名.class类名"); // namespace.class

" 在dll文件内获取 所有class类型"
Type[]  all_class_Type = assembly4.GetTypes(); // namespace.class

5类型实例化class

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

// 实例化class
//RedlectionTest obj = new RedlectionTest();// 这种是知道具体类型

" 创建类的实例"       【构造方法激活器。创建实例】 默认public构造方法
object 风韵犹存的少妇 = Activator.CreateInstance(class_Type);// 创建的是class【构造方法】

// 创建其他的有参构造                        数组构造方法,带1个参数
object 风韵犹存的少妇2 = Activator.CreateInstance(class_Type,new object[]{"带一个参数的构造方法","数组第2个对象的构造方法"});// 创建的是class【构造方法】

// 私有构造方法                            私有构造方法
object 风韵犹存的少妇3 = Activator.CreateInstance(class_Type,True);//创建的是class【构造方法】

 static void Main(string[] args)
        {
            " 加载外部DLL"        【集合。加载】
            Assembly assembly = Assembly.LoadFrom("External.dll");

            " 获取DLL中的类"      【集合。获取类型】
            Type type = assembly.GetType("External.ExternalClass");

            " 创建类的实例化"       【激活器。方法】
            object instance = Activator.CreateInstance(type);

            " 调用类中的方法"     【类型Get方法】
            MethodInfo method = type.GetMethod("ExternalMethod");
            method.Invoke(instance, null);
        }

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

Get所有构造方法

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

Get私有方法

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

Get参数

.GetParameters();

6获取所有class类型

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

foreach( var class_Type in  assembly4.GetTypes())  // 所有class类型
{
    Console.WriteLine(class_Type.Name);  // class类型名
}


"class所有的构造方法"
class.GetConstructors();
foreach( var class_构造 in  class_Type.GetConstructors(【标签】))  // 所有class类型
{
    Console.WriteLine(class_构造.Name);  // class所有构造方法
}
//========================
【标签】        实例化的,私有的,公有的
BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public
//========================

"构造方法的所有参数类型"
class_构造.GetParameters();
foreach( var param in  class_构造.GetParameters())  // 所有class类型
{
    Console.WriteLine(param.ParameterType);  // 构造方法的 参数
}


//==============================
方法A  方法a = 风韵犹存的少妇3 as 方法A;  裁剪出方法

 7调用私有方法

私有方法

// 私有构造方法                            私有构造方法
object 风韵犹存的少妇3 = Activator.CreateInstance(class_Type,True);//创建的是class【构造方法】

//========================
【标签】        实例化的,私有的,公有的
BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public
//========================
var 方法a = class_Type.GetMethod("方法A",【标签】);
方法a.Invoke(风韵犹存的少妇3,new object[]{});






8实例化对象  s们  class

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

//=================================
" 在dll文件内获取class类型"
Type  class_Type = assembly4.GetType("命名空间名.class类名"); // namespace.class

foreach( var item in  assembly4.GetTypes())  // 所有class对象
{
    Console.WriteLine(item.Name);  // class 对象名
}

// 所有构造方法
foreach( var item in  class_Type.GetConstructors(BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public))  // 所有class对象【实例,私有,公开】
{
    Console.WriteLine(item.Name);  //  所有class对象
    foreach( var param in  item.GetParameters())  // 对象.all参数【所有参数】
    {
      Console.WriteLine(param.ParameterType);  //    对象.参数类型
    }
}

using System;
using System.Reflection;

public class MyClass
{
    public void MyMethod(int x)
    {
        Console.WriteLine(x);
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 获取MyClass类型的Type对象
        Type myType = typeof(MyClass);

        // 创建MyClass的实例  【激活器。方法】
        object obj = Activator.CreateInstance(myType);

        // 获取MyMethod方法的MethodInfo对象    【方法信息】
        MethodInfo myMethod = myType.GetMethod("MyMethod");

        // 调用MyMethod方法
        myMethod.Invoke(obj, new object[] { 123 });
    }
}
这个Demo首先定义了一个MyClass类,其中包含一个MyMethod方法。
然后在Main方法中,
通过typeof获取MyClass类型的Type对象,
再通过Activator.CreateInstance创建MyClass的实例。

接着,通过Type.GetMethod获取MyMethod方法的MethodInfo对象,
最后通过MethodInfo.Invoke调用MyMethod方法并传入参数。

2dll文件

using System;
using System.Reflection;

namespace ReflectionDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            " 加载外部DLL"        【集合。加载】
            Assembly assembly = Assembly.LoadFrom("External.dll");

            " 获取DLL中的类"      【集合。获取类型】
            Type type = assembly.GetType("External.ExternalClass");

            " 创建类的实例"       【激活器。方法】
            object instance = Activator.CreateInstance(type);

            " 调用类中的方法"     【类型Get方法】
            MethodInfo method = type.GetMethod("ExternalMethod");
            method.Invoke(instance, null);
        }
    }
}
上述代码中,我们首先使用Assembly.LoadFrom方法加载外部DLL文件,
然后使用GetType方法获取DLL中的类,
接着使用Activator.CreateInstance方法创建类的实例,

最后使用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】准备材料:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace lookme
{
    public class me
    {
        int ziduan;
        int ziduan2 = 66;
        int 字段;
        int 字段2 = 77;

        public int shuxing { get; set; }
        public int shuxing2 { get; set; } = 77;
        public int 属性 { get; set; }
        public int 属性2 { get; set; } = 88;

        void fun()
        {
            int i = 0;
            i += 1;
        }
       public  int fun2()
        {
            ++ziduan;
            return ziduan;

            //++i;
            //return i;
        }
        void 方法()
        {
            int i=0;
            i+=1;
        }
       public  void 方法2()
        {
            int i = 0;
            i += 1;
        }

    }
}

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

 运行后会生成   exe文件

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

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

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

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

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

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

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

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

Assembly ass1 = Assembly.LoadFrom("登录窗.exe");//需要将登录窗.exe文件复制到\bin\Debug文件下

Assembly ass2 = Assembly.LoadFile(System.IO.Directory.GetCurrentDirectory() + "\\InterfaceAndPolymorphism.exe");// 文件路径

Assembly ass3 = Assembly.Load("InterfaceAndPolymorphism");//程序集名称

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

//  加载exe文件路径
try
   {
      //Assembly ass1 = Assembly.LoadFrom(assName);//需要将登录窗.exe文件复制到\bin\Debug文件下
      Assembly ass2 = Assembly.LoadFile(@"C:\Users\Administrator\Desktop\lookme\lookme\lookme\bin\Debug\lookme.exe");
      //Assembly ass3 = Assembly.Load("InterfaceAndPolymorphism");//程序集名称

      if (ass2 == null) throw new Exception();

      return ass2;
   }
catch (Exception ex)
   {
       MessageBox.Show(ex.Message);
       throw ex; 
   }//显示错误

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

 【3】获取新建对象

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

 1先查看里面有什么

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

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

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

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

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

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

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

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

 

 

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

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

以下是一个C#反射的入门Demo,它可以通过反射获取类的信息并调用其中的方法:

using System;
using System.Reflection;

public class MyClass
{
    public void MyMethod(int x)
    {
        Console.WriteLine(x);
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 获取MyClass类型的Type对象
        Type myType = typeof(MyClass);

        // 创建MyClass的实例
        object obj = Activator.CreateInstance(myType);

        // 获取MyMethod方法的MethodInfo对象
        MethodInfo myMethod = myType.GetMethod("MyMethod");

        // 调用MyMethod方法
        myMethod.Invoke(obj, new object[] { 123 });
    }
}
这个Demo首先定义了一个MyClass类,其中包含一个MyMethod方法。然后在Main方法中,通过typeof获取MyClass类型的Type对象,再通过Activator.CreateInstance创建MyClass的实例。接着,通过Type.GetMethod获取MyMethod方法的MethodInfo对象,最后通过MethodInfo.Invoke调用MyMethod方法并传入参数。


dll文件,用C#写个反射demo

以下是一个使用C#反射技术动态加载外部DLL并调用其中方法的示例代码:

using System;
using System.Reflection;

namespace ReflectionDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // 加载外部DLL
            Assembly assembly = Assembly.LoadFrom("External.dll");

            // 获取DLL中的类
            Type type = assembly.GetType("External.ExternalClass");

            // 创建类的实例
            object instance = Activator.CreateInstance(type);

            // 调用类中的方法
            MethodInfo method = type.GetMethod("ExternalMethod");
            method.Invoke(instance, null);
        }
    }
}
上述代码中,我们首先使用Assembly.LoadFrom方法加载外部DLL文件,然后使用GetType方法获取DLL中的类,接着使用Activator.CreateInstance方法创建类的实例,最后使用GetMethod方法获取类中的方法并使用Invoke方法调用该方法。

详细讲下C#反射

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

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

反射的基本用法
(1)获取类型信息

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

Type type1 = typeof(string); // 获取string类型的Type对象
Type type2 = "hello".GetType(); // 获取字符串"hello"的Type对象
(2)创建类型实例

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

Type type = typeof(MyClass); // 获取MyClass类型的Type对象
object obj = Activator.CreateInstance(type); // 创建MyClass类型的实例
(3)访问成员

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

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方法调用类型的方法。例如:

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值