1、反射的代码层面的用途
1)使用Assembly
定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。
2)使用Module
了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
3)使用ConstructorInfo
了解构造函数的名称、参数、访问修饰符(如pulic
或private
)和实现详细信息(如abstract
或virtual
)等。
4)使用MethodInfo
了解方法的名称、返回类型、参数、访问修饰符(如pulic
或private
)和实现详细信息(如abstract
或virtual
)等。
5)使用FiedInfo
了解字段的名称、访问修饰符(如public
或private
)和实现详细信息(如static
)等,并获取或设置字段值。
6)使用EventInfo
了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
7)使用PropertyInfo
了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
8)使用ParameterInfo
了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等
2、反射用到命名空间
System.Reflection
System.Type
System.Reflection.Assembly
3、反射用到类和方法
System.Type 类:通过这个类可以访问任何给定数据类型的信息。 对于反射起着核心的作用。但它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。
System.Reflection.Assembly类:它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。
1) 获取给定类型的Type引用有3种常用方式
使用 C# typeof 运算符:
Type t = typeof(string);
使用对象GetType()方法:
string s = "grayworm";
Type t = s.GetType();
调用Type类的静态方法GetType():
Type t = Type.GetType("System.String");
上面这三类代码都是获取string类型的Type,在取出string类型的Type引用t后,我们就可以通过t来查看string类型的结构了。
string n = "grayworm";
Type t = n.GetType();
foreach (MemberInfo mi in t.GetMembers())
{
Console.WriteLine("{0}/t{1}",mi.MemberType,mi.Name);
}
2) Type类的属性
Name:数据类型名
FullName: 数据类型的完全限定名(包括命名空间名)
Namespace: 定义数据类型的命名空间名
IsAbstract: 指示该类型是否是抽象类型
IsArray: 指示该类型是否是数组
IsClass:指示该类型是否是类
IsEnum:指示该类型是否是枚举
IsInterface:指示该类型是否是接口
IsPublic:指示该类型是否是公有的
IsSealed:指示该类型是否是密封类
IsValueType:指示该类型是否是值类型
3) Type类的方法
GetConstructor(), GetConstructors():返回ConstructorInfo
类型,用于取得该类的构造函数的信息
GetEvent(), GetEvents():返回EventInfo
类型,用于取得该类的事件的信息
GetField(), GetFields():返回FieldInfo
类型,用于取得该类的字段(成员变量)的信息
GetInterface(), GetInterfaces():返回InterfaceInfo
类型,用于取得该类实现的接口的信息
GetMember(), GetMembers():返回MemberInfo
类型,用于取得该类的所有成员的信息
GetMethod(), GetMethods():返回MethodInfo
类型,用于取得该类的方法的信息
GetProperty(), GetProperties():返回PropertyInfo
类型,用于取得该类的属性的信息
可以调用这些成员,其方式是调用Type的InvokeMember()
方法,或者调用MethodInfo
, PropertyInfo
和其他类的Invoke()
方法。
4、使用示例代码
1) 查看类中的构造方法
NewClassw nc = new NewClassw();
Type t = nc.GetType();
ConstructorInfo[] ci = t.GetConstructors(); //获取类的所有构造函数
foreach (ConstructorInfo c in ci) //遍历每一个构造函数
{
ParameterInfo[] ps = c.GetParameters(); //取出每个构造函数的所有参数
foreach (ParameterInfo pi in ps) //遍历并打印所该构造函数的所有参数
{
Console.Write(pi.ParameterType.ToString() + " " + pi.Name + ",");
}
Console.WriteLine();
}
2) 用构造函数动态创建对象
Type t = typeof(NewClassw);
Type[] pt = new Type[2];
pt[0] = typeof(string);
pt[1] = typeof(string);
//根据参数类型获取构造函数
ConstructorInfo ci = t.GetConstructor(pt);
//构造Object数组,作为构造函数的输入参数
object[] obj = new object[2]{"grayworm","hi.baidu.com/grayworm"};
//调用构造函数生成对象
object o = ci.Invoke(obj);
//调用生成的对象的方法测试是否对象生成成功
//((NewClassw)o).show();
3) 用Activator创建对象
Type t = typeof(NewClassw);
//构造函数的参数
object[] obj = new object[2] { "grayworm", "hi.baidu.com/grayworm" };
//用Activator的CreateInstance静态方法,生成新对象
object o = Activator.CreateInstance(t,"grayworm","hi.baidu.com/grayworm");
//((NewClassw)o).show();
4) 查看类中的属性
NewClassw nc = new NewClassw();
Type t = nc.GetType();
PropertyInfo[] pis = t.GetProperties();
foreach(PropertyInfo pi in pis)
{
Console.WriteLine(pi.Name);
}
5) 查看类中的public方法
NewClassw nc = new NewClassw();
Type t = nc.GetType();
MethodInfo[] mis = t.GetMethods();
foreach (MethodInfo mi in mis)
{
Console.WriteLine(mi.ReturnType+" "+mi.Name);
}
6) 查看类中的public字段
NewClassw nc = new NewClassw();
Type t = nc.GetType();
FieldInfo[] fis = t.GetFields();
foreach (FieldInfo fi in fis)
{
Console.WriteLine(fi.Name);
}
7) 用反射生成对象,并调用属性、方法和字段进行操作
NewClassw nc = new NewClassw();
Type t = nc.GetType();
object obj = Activator.CreateInstance(t);
//取得ID字段
FieldInfo fi = t.GetField("ID");
//给ID字段赋值
fi.SetValue(obj, "k001");
//取得MyName属性
PropertyInfo pi1 = t.GetProperty("MyName");
//给MyName属性赋值
pi1.SetValue(obj, "grayworm", null);
PropertyInfo pi2 = t.GetProperty("MyInfo");
pi2.SetValue(obj, "hi.baidu.com/grayworm", null);
//取得show方法
MethodInfo mi = t.GetMethod("show");
//调用show方法
mi.Invoke(obj, null);
5、使用System.Reflection.Assembly类动态加载程序集(.dll)
Assembly类可以获得程序集的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例。 使用Assembly类可以降低程序集之间的耦合,有利于软件结构的合理化。
通过程序集名称返回Assembly对象
Assembly ass = Assembly.Load("ClassLibrary831");
通过DLL文件名称返回Assembly对象
Assembly ass = Assembly.LoadFrom("ClassLibrary831.dll");
通过Assembly获取程序集中类
Type t = ass.GetType("ClassLibrary831.NewClass"); //参数必须是类的全名
通过Assembly获取程序集中所有的类
Type[] t = ass.GetTypes();
//通过程序集的名称反射
Assembly ass = Assembly.Load("ClassLibrary831");
Type t = ass.GetType("ClassLibrary831.NewClass");
object o = Activator.CreateInstance(t, "grayworm", "http://hi.baidu.com/grayworm");
MethodInfo mi = t.GetMethod("show");
mi.Invoke(o, null); //通过DLL文件全名反射其中的所有类型
Assembly assembly = Assembly.LoadFrom("xxx.dll的路径");
Type[] aa = a.GetTypes();
foreach(Type t in aa)
{
if(t.FullName == "a.b.c")
{
object o = Activator.CreateInstance(t);
}
}