什么是反射?
反射是.net framework提供的一个帮助类库,可以访问dll/exe的metadata(元数据),并且使用他们。
元数据(Metadata),又称中介数据、中继数据,是为了描述数据的数据,主要是描述数据属性的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。
使用反射
简单使用
#region 用反射机制获取程序集中的属性与方法(元数据)
{
// 获取所在的dll的信息
foreach (var item in assembly.GetModules())
{
// 获取dll的名称
Console.WriteLine(item.Name);
}
// 获取dll的类型 {Name = "Student" FullName = "Models.Student"}
foreach (var type in assembly.GetTypes())
{
Console.WriteLine(type.Name);
// 获取指定类型的方法,方法中包含{字段的get,set方法、自定义方法、默认方法(Equals、GetHashCode、GetType、ToString等)}
foreach (var method in type.GetMethods())
{
Console.WriteLine(method.Name);
}
}
}
#endregion
反射调用构造函数(IOC的雏形)
反射调用无参数构造函数
#region 用反射的机制创建对象(调用无参的构造函数)
{
// 获取对应类型
Type type = assembly.GetType("Models.Student");
// 创建对象
object vobj = Activator.CreateInstance(type);
// 使用对象记得转换对象类型
Student student = vobj as Student;
// 使用对象方法
student.write();
}
#endregion
反射调用带参数的构造函数
#region 调用带参数的构造函数
{
Type type = assembly.GetType("Models.Student");
//创建一个带两个参数的构造函数
object obj = Activator.CreateInstance(type, new object[] { 1,"zs" });
//使用方法
Student student = obj as Student;
student.write();
}
#endregion
反射调用泛型类构造
#region 获取泛型类,调用泛型构造
{
//这里注意,使用`2的形式,指定类型的泛型参数格式
Type type = assembly.GetType("Models.GenericStudent`2");
Type typeGenereic = type.MakeGenericType(typeof(int), typeof(string));
//调用泛型构造函数,构建对象
object obj = Activator.CreateInstance(typeGenereic,new object[] { 1,"lisi"});
//使用方法
GenericStudent<int, string> student = obj as GenericStudent<int,string>;
student.write();
}
#endregion
反射调用私有构造函数
#region 反射调用私有构造函数
{
// 用这种方式可以破坏单例模式
Type type = assembly.GetType("Models.Teacher");
// 调用私有构造函数,指定nonpublic为true,代表可以反问私有的构造方法。
object obj = Activator.CreateInstance(type, true);
}
#endregion
反射调用方法
反射调用普通方法
#region 反射调用方法
{
Type type = assembly.GetType("Models.Student");
object vobj = Activator.CreateInstance(type);
MethodInfo methodInfo = type.GetMethod("write");
methodInfo.Invoke(vobj, null);
}
#endregion
反射调用特殊方法(带参数的、静态的、重载的、私有的、泛型的)
调用泛型方法
反射动态获取/赋值属性字段
#region 反射动态获取/赋值属性字段
//通常当使用到一个实体类的反射时,是不会从头(程序集Assmbly找起的)
{
Type type = typeof(Student);
// 实例化当前类型
object obj = Activator.CreateInstance(type);
//遍历获取类型判断并赋值
foreach (var item in type.GetProperties())
{
if (item.Name.Equals("id"))
{
item.SetValue(obj,1);
}
if (item.Name.Equals("name"))
{
item.SetValue(obj, "lisi");
}
}
}
#endregion
泛型的好处与局限
好处:动态,将写死的东西可以用反射来动态来创建。
局限:
1、代码繁琐
2、反射能避开编译器的语法检查、编译检查,运行时才报错
3、性能问题(不是很大的问题):反射是普通方法的性能损耗百倍以上,但是绝对值还是蛮小的,几乎不影响项目的性能。
反射和缓存是离不开的,通常将固定的的反射的一些步骤缓存起来。而上一章的泛型缓存就非常适合。性能很高。