反射(2)使用反射

  这一篇文章来总结下怎么使用反射的。

加载程序集

要加载程序集,可以调用 Assembly的LoadXXX系列方法。

1,Assembly.Load方法

1 //1,从GAC或应用程序基目录加载程序集
2 var assembly = Assembly.Load("ReflectionDemo.A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");//或ReflectionDemo.A也可以

需要注意的是:

1)查找顺序,首先去GAC查找,如果没找到,则去应用程序的基目录查找,如果都没找到,则会抛出FileNotFoundException的异常。

2)Load参数一般为应用程序集名称的长格式,如:ReflectionDemo.A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null,也可以直接ReflectionDemo.A。

2,Assembly.LoadFrom方法

1 //2,从一个url加载程序集
2 var assembly = Assembly.LoadFrom(@"http://www.a.com/ReflectionDemo.A.dll"); 

Assembly.LoadFrom的内部其实是调用Assembly.Load方法,唯一的不同在于,其可以从一个网络url中加载程序集。

3,Assembly.LoadFile方法

1 //3,从本地路径加载程序集
2 var path = string.Format(@"{0}\{1}", AppDomain.CurrentDomain.BaseDirectory, @"plugins\ReflectionDemo.A.dll");
3 var assembly = Assembly.LoadFile(path);

Assembly.LoadFile允许从本地不同路径加载程序集。

查找程序集内所有类型

反射的入口Type类,Type对象提供的属性和方法可以获取对明的一切信息,包括:字段,属性,方法和事件等等。

在已经加载了程序集的基础上,能过以下方式可以获取到Type对象。

 1 /// <summary>
 2 /// 获取程序集中所有的公共类型
 3 /// </summary>
 4 /// <param name="assembly"></param>
 5 static void GetExportedTypes(Assembly assembly)
 6 {
 7     var types = assembly.GetExportedTypes();
 8     foreach (var item in types)
 9     {
10         Console.WriteLine(item.Name);
11     }
12 }
1 /// <summary>
2 /// 获取程序集中具名的类型
3 /// </summary>
4 /// <param name="assembly"></param>
5 static void GetType(Assembly assembly)
6 {
7     var t = assembly.GetType("ReflectionDemo.A.Class1");
8     Console.WriteLine(t.Name);
9 }

查找类型成员

在命名空间System.Reflection下有一个抽象类MemberInfo,它封装了与类型成员相关的通用属性,每一个类型成员都有一个对应的从MemberInfo派生而来的类型,并且内置了一些特殊的属性特征,如FieldInfo、MethodBase(ContructorInfo、MethodInfo)、PropertyInfo和EventInfo。可以通过调用类型Type对象的GetMembers方法获取该类型的所有成员或相应成员,如下代码(对上面的GetTypes方法的修改)获取全部成员列表:

 1 /// <summary>
 2 /// 获取类型成员
 3 /// </summary>
 4 /// <param name="t"></param>
 5 static void GetMembers(Type t)
 6 {
 7     var members= t.GetMembers();
 8     foreach (var item in members)
 9     {
10         Console.WriteLine(item.Name);
11     }
12 }

Type对象有一组GetXXX方法是用来获取对象成员的,如下:

GetConstructor/GetConstructors //获取构造函数
GetField/GetFields //获取字段
GetProperty/GetProperties //获取属性
GetMethod/GetMethods //获取方法
GetEvent/GetEvents //获取事件

看下MemberInfo的结构:

构造类型实例

拿到类型和成员相关信息后,就可以创建类型的实例了,创建类型实例有以下几种方法:

1 Activator.CreateInstance() //重载系列
2 Activator.CreateInstanceFrom() //重载系列
3 AppDomain.CurrentDomain.CreateInstance() //重载系列
4 AppDomain.CurrentDomain.CreateInstanceFrom() //重载系列

下面就来创建一个ReflectionDemo.A.Class1的实例(对象),如下代码:

1 /// <summary>
2 /// 创建类型实例
3 /// </summary>
4 static void CreateInstance(Assembly assembly)
5 {
6     var t = assembly.GetType("ReflectionDemo.A.Class1");
7     var obj = Activator.CreateInstance(t);
8 }

访问实例成员

创建了类型的实例后,就可以调用实例的成员方法了,如下代码:

 1 /// <summary>
 2 /// 动态调用方法
 3 /// </summary>
 4 /// <param name="assembly"></param>
 5 static void InvokeMethod(Assembly assembly)
 6 {
 7     var t = assembly.GetType("ReflectionDemo.A.Class1");
 8     var obj = Activator.CreateInstance(t);
 9
10     var name = t.InvokeMember("GetName", BindingFlags.InvokeMethod, null, obj, null);
11 }

上面演示了动态调用实例成员,访问实例其它成员可以通过BindingFlags来改变。

反射对泛型的支持

前面演示的都是普通类型,如果是泛型,该怎么处理呢?

首先定义一个泛型类,如下:

 1 namespace ReflectionDemo.A
 2 {
 3     public class Class2<T> where T : class
 4     {
 5         public string GetName<T>(T name)
 6         {
 7             return string.Format("generic name,{0}", name.ToString());
 8         }
 9     }
10 }

演示一下如何调用泛型类的GetName方法,如下代码:

 1 /// <summary>
 2 /// 访问泛型类型成员
 3 /// </summary>
 4 /// <param name="assembly"></param>
 5 static void InvokeGenericMethod(Assembly assembly)
 6 {
 7     var types = assembly.GetExportedTypes();
 8     foreach (var item in types)
 9     {
10         if (item.IsGenericType)//1,先判断是否为泛型
11         {
12             var obj = Activator.CreateInstance(item.MakeGenericType(new Type[] { typeof(string) }));//2,在创建泛型类实例前,必须调用MakeGenericType创建一个真正的泛型
13             var methodInfo = obj.GetType().GetMethod("GetName").MakeGenericMethod(new Type[] { typeof(string) });//3,在调用泛型方法前,必须调用MakeGenericMethod创建一个真正的泛型方法
14
15             var name = methodInfo.Invoke(obj, new object[] { "aaa" });
16             Console.WriteLine(name);
17         }
18     }
19 }
时间: 2024-10-11 13:39:44

反射(2)使用反射的相关文章

反射机制,反射的性能,如何优化?

反射机制的定义: 是在运行状态中,对于任意的一个类,都能够知道这个类的所有属性和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息及动态调用类对象方法的功能称为java的反射机制. 反射的作用: 1.动态地创建类的实例,将类绑定到现有的对象中,或从现有的对象中获取类型. 2.应用程序需要在运行时从某个特定的程序集中载入一个特定的类.

java 反射和暴力反射 两个DEMO

该类为反射函数 获取和暴力获取ReflectPoin类中的属性 package com.tuozou.test; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class ReflectTest { public ReflectTest() { // TODO Auto-generated con

Java 反射机制[Field反射]

Java 反射机制[Field反射] 1.  反射概念及功能 反射就是把Java类中的各种成分映射成相应的Java类.例如一个Java类中用一个Class类的对象来表示.一个类中的组成部分分为成员变量,方法,构造方法,包等等. Java反射机制主要提供了以下功能: 判断在运行时任意一个对象所属的类:在运行时构造任意一个类的对象:判断在运行时任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理. 2.  Field反射 以下代码将obj对象中的String类型的字段对应的

Java 反射机制[Method反射]

Java 反射机制[Method反射] 接着上一篇Java 反射机制[Field反射],通过调用Person类的setName方法将obj的name字段的Value设置为"callPersonSetNameMethod"来了解什么是Method反射.示例代码很简单,很容易理解. 可以看到Method.invoke()实际上并不是自己实现的反射调用逻辑,而是委托给sun.reflect.MethodAccessor来处理. 真正的反射是调用MethodAccessor.invoke()真

java反射-反射实例化对象-反射获得构造方法-反射获得普通方法-获得属性

链接:https://www.zhihu.com/question/24304289/answer/38218810来源:知乎著作权归作者所有,转载请联系作者获得授权. Class<?> cls = Class.forName("cn.mldn.demo.Person"); // 取得Class对象 第一步:获得对象,构造方法,普通方法,属性 Object obj = cls.newInstance() Constructor<?> cons = cls.get

[javaSE] 反射-方法的反射

1.如何获取某个方法 方法的名称和方法的参数列表才能唯一决定一个方法 2.方法反射的操作 method.invoke(); package com.tsh.reflect; import java.lang.reflect.Method; public class ReflectDemo { public static void main(String[] args) { P p=new P(); Class c=P.class; try { Method method=c.getDeclare

反射认识_02_反射成员变量Field

包01: package ReflectionConstructor; public class ReflectionFieldPoint { private int x; public int y; public ReflectionFieldPoint(int x, int y) { super(); this.x = x; this.y = y; } } 包02:package ReflectionConstructor; import java.lang.reflect.Field; /

反射认识_01_反射构造方法

package ReflectionConstructor; import java.lang.reflect.Constructor; /** * 调用String的构造方法 将StringBuffer类转换成String类 */public class ReflectionConstructor { public static void main(String[] args) throws Exception { // 原始转换 StringBuffer sb = new StringBuf

PHP反射之类的反射

最近在琢磨如何用PHP实现站点的插件功能,需要用到反射,于是现学了一下,笔记如下: class Person { public $name = 'Lily'; public $gender = 'male'; public $age = 20; public function eat() { echo 'Lily is eating!'; } public function run() { echo 'Lily is running!'; } } $ref = new ReflectionCla

java 27 - 8 反射之 通过反射来设置某个对象的某个属性为指定值

标题的意思是: 通过反射写一个类,类中有个方法.该方法可以设置某个类中的某个属性(构造方法,成员变量,成员方法)为特定的值 代码: 1 // 该方法的参数列表是一个类的 类名.成员变量.给变量的赋值 2 public void setProperty(Object obj, String PropertyName, Object value) 3 throws NoSuchFieldException, SecurityException, 4 IllegalArgumentException,