1:反射的原理:
反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等,。System.reflection命名空间包含的几个类,允许你反射(解析)这些元数据表的代码
这段话不太好理解:首先什么是元数据? 上面虽然有解释,但是会是一头雾水,可以先看下:
https://blog.csdn.net/xulong5000/article/details/105222822 这里面专门讲解了什么是元数据,
其实就是运行库的中间语言会把你写的方法快速的本机指令,是二进制的形成存在。放在内存中,根据反射技术可以去读取并且调用到内部的方法。
反射的作用:
1. 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现 有对象中获取类型
2. 应用程序需要在运行时从某个特定的程序集中载入一个特定的类型,以便实现某个任务时可以用到反射。
3. 反射主要应用与类库,这些类库需要知道一个类型的定义,以便提供更多的功能。
应用要点:
1. 现实应用程序中很少有应用程序需要使用反射类型
2. 使用反射动态绑定需要牺牲性能
3. 有些元数据信息是不能通过反射获取的
4. 某些反射类型是专门为那些clr 开发编译器的开发使用的,所以你要意识到不是所有的反射类型都是适合每个人的。
案例:
1:单纯的反射实例化对象调用方法
分为带参数的反射跟不带参数的反射
这里需要注意: var t = Type.GetType(className);
object obj = Activator.CreateInstance(t);
这两个代码,这里没有用到Assembly,而是直接用 Type获取类,className是 命名空间+类名
methodName 是方法名字
MethodInfo这个是返回接受的类型,具体到某个方法就是 MethodInfo ,如果是t.GetMethods() 就返回的是:MethodInfo[]
Object[] 是反射传参数的方法,不能直接根据方法参数类型来传,全部默认是对象数组传
private static void Typeinfo()
{
//反射获取 命名空间+类名
string className = "Reflection.ClassSample";
string methodName = "test1";
//传递参数
Object[] paras = new Object[] { "我的", "电脑" };
// 这里 className如果是第三方的dll,就会报错,因为不在相同的程序集中,需要使用assembly来调用
var t = Type.GetType(className);
object obj = Activator.CreateInstance(t);
//object any = new object();
try
{
//直接调用
MethodInfo method = t.GetMethod("test2");
method.Invoke(obj, paras);
}
catch (Exception ex)
{
throw ex;
}
Console.ReadKey();
}
2:用委托+反射 来做
这里为什么要用到委托,因为反射太耗性能了,所以在实际情况下,代码里面不会直接使用反射来调用。所以需要用到一些其他技术来配合,例如:委托 跟反射一起调用程序集里面的方法,性能会有很好的提升
class MainClass
{
const int loops = 100000000;
Action m_Action; // 声明一个委托,这个是系统内带的委托,也可以自定义委托
public MainClass()
{
Type t = Type.GetType("Delegate.Refl.Test");
MethodInfo m = t.GetMethod("Method");
m_Action = (Action)System.Delegate.CreateDelegate(typeof(Action), m_Test, m);
}
public void Test2()
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0; i < loops; ++i)
{
m_Action();
}
stopWatch.Stop();
Console.WriteLine("Test2 - delegate invoke: " + stopWatch.ElapsedMilliseconds);
}
}
static void Main(string[] args)
{
MainClass main = new MainClass();
main.Test2();
Console.ReadKey();
}