什么是反射,反射能干嘛? 您所在的位置:网站首页 keys方法可以干嘛 什么是反射,反射能干嘛?

什么是反射,反射能干嘛?

2024-07-08 03:37| 来源: 网络整理| 查看: 265

原文链接:农码一生

反射是:指程序可以访问、检测和修改它本身状态或行为的一种能力。 反射是一种能力,所以给的定义就是说明了它能干嘛。 我们平时用反射主要做:

1、获取类型的相关信息 2、动态调用方法 3、动态构造对象 4、从程序集中获得类型

1、获取类型的相关信息

反射的核心Type类,Type对象提供的属性和方法可以获取对象的一切信息。如:方法、字段、属性、事件……等。

我们获取已加载程序集中类型的Type对象的几种方法:(以StringBuilder类型为例)

1、直接使用typeof操作符 Type t1 = typeof(StringBuilder); 2、通过类型实例Type t2 = new StringBuilder().GetType(); 3、通过Type类的静态方法Type t3 = Type.GetType("System.IO.Stream");

不管使用那种,我们最终得到的结果都是一样的。那么我们通过Type又能得到些什么信息呢?

Type T1 = typeof(StringBuilder); Console.WriteLine("命名空间名称:" + T1.Namespace); Console.WriteLine("直接基类型:" + T1.BaseType); Console.WriteLine("全名:" + T1.FullName); Console.WriteLine("是抽象类型:" + T1.IsAbstract); Console.WriteLine("是类:" + T1.IsClass);

2、动态调用方法

public class TClass { public void fun(string str) { Console.WriteLine("我是fun方法,我被调用了。" + str); } public void fun2() { Console.WriteLine("我是fun2方法,我被调用了。"); } public static void fun3() { Console.WriteLine("我是fun3静态方法,我被调用了"); } }

调用方式一(使用InvokeMember调用方法)

//1、调用带参实例方法fun Type T1 = typeof(TClass); T1.InvokeMember("fun", BindingFlags.InvokeMethod, null, new TClass(), new string[] { "test" }); //2、调用无参实例方法fun2 Type T1 = typeof(TClass); T1.InvokeMember("fun2", BindingFlags.InvokeMethod, null, new TClass(), null); //3、调用静态方法 Type T1 = typeof(TClass); T1.InvokeMember("fun3", BindingFlags.InvokeMethod, null, T1, null);

调用方式二(使用MethodInfo.Invoke调用方法)

Type T1 = typeof(TClass); T1.GetMethod("fun", BindingFlags.Instance | BindingFlags.Public).Invoke(new TClass(), new string[] { "testfun1" }); T1.GetMethod("fun2", BindingFlags.Instance | BindingFlags.Public).Invoke(new TClass(), null); T1.GetMethod("fun3", BindingFlags.Static | BindingFlags.Public).Invoke(T1, null);

真正的全动态调用 上面的两种方式,在编写代码的时候总是要先确定了已知的对象名和方法名。那么我们在不知道对象和方法名的时候是否也可以调用呢?答案是肯定的,实现如下:

Console.WriteLine("请输入对象类名"); string className = Console.ReadLine(); Console.WriteLine("请输入要执行的方法名"); string funName = Console.ReadLine(); Type T1 = Type.GetType(className); ConstructorInfo ci = T1.GetConstructors()[0]; //获取构造函数 var obj = ci.Invoke(null);//实例化构造函数 T1.InvokeMember(funName, BindingFlags.InvokeMethod, null, obj, null);

3、动态构造对象

public class TClass { public TClass() { Console.WriteLine("构造函数被执行了。。"); } public TClass(string str) { Console.WriteLine("有参构造函数被执行了。。" + str); } }

动态构造对象

/动态构造对象,方式一 Assembly asm = Assembly.GetExecutingAssembly(); TClass obj = (TClass)asm.CreateInstance("net.tclass", true);//true:不区分大小写 //动态构造对象,方式二 ObjectHandle handler = Activator.CreateInstance(null, " net.TClass");//null:当前程序集 obj = (TClass)handler.Unwrap(); //动态构造对象,方式三(构造有参构造函数) Assembly asm2 = Assembly.GetExecutingAssembly(); obj = (TClass)asm2.CreateInstance("net.tclass", true, BindingFlags.Default, null, new string[] { "test" }, null, null);//true:不区分大小写

获取和修改属性:

var obj = new TClass(); obj.name = "张三"; Type type = typeof(TClass); //获取属性 var Name = type.InvokeMember("name", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, obj, new object[] { }) as string; Console.WriteLine(obj.name); //设置属性 type.InvokeMember("name", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, obj, new object[] { "新属性(李四)" }); Console.WriteLine(obj.name);

从程序集中获得类型 取得当前代码所在程序集(使用GetExecutingAssembly)

Assembly ass = Assembly.GetExecutingAssembly(); Console.WriteLine("当前所在程序集名:"+ass.ManifestModule.Name); Console.WriteLine("当前所在程序集路径:"+ass.Location);

通过反射加载程序集并创建程序中的类型对象 从程序集中获得类型,这个应该是我们平时用得比较多。如我们所谓的依赖注入和控制反转(这个主题将在下篇博文进行分析)就用到了通过反射从程序集中获取类型。

首先我们还是看看怎么从程序集中获得类型吧。我们可以使用Assembly类型提供的静态方法LoadFrom()或Load(),如:

Assembly asm = Assembly.LoadFrom("Demo.dll"); Assembly asm = Assembly.Load("Demo");

区别:

Assembly asm = Assembly.LoadFrom("net.exe");//需要加后缀,可以指定路径,如下面的 Assembly asm1 = Assembly.LoadFrom(@"C:\01文件\05Svn\BlogsCode\Blogs\Blogs.Web\bin\Blogs.BLL.dll"); Assembly asm2 = Assembly.Load("Blogs.BLL");//无需加后缀,不可以指定路径 //Assembly asm3 = Assembly.Load(@"C:\01文件\05Svn\BlogsCode\Blogs\Blogs.Web\bin\Blogs.BLL");//这里会报错 //使用Load可以加载当前程序bin目录行下的程序集或者系统程序集 //这里TClass可以是一个接口,那么可以在外面的dll任意实现了。 TClass obj = (TClass)asm2.CreateInstance("net.tclass", true);//true:不区分大小写 obj.fun();//***调用动态加载的dll中的方法***

在讲依赖注入的时候会讲到,同学们继续关注哦~)

从上所知,反射不是某一个概念,而是一类操作的统称。或者说是某些能力的统称。 感觉不好回答反射到底是什么,只能说反射能干什么。它能动态创建对象、动态调用对象方法、动态读取和设置属性和字段、它能动态加载程序外的dll。总的感觉就是大多数都是跟“动态”扯上了关系。

学习本是一个不断抄袭、模仿、练习、创新的过程。 虽然,园中已有本人无法超越的同主题博文,为什么还是要写。 对于自己,博文只是总结。在总结的过程发现问题,解决问题。 对于他人,在此过程如果还能附带帮助他人,那就再好不过了。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有