参考文章:
1、反射是动态执行的(和oc的动态性类似),使用反射是开销非常大的调用方式,效率会比直接引用低,也可能会存在很多的异常,用时需谨慎。一般情况下,可以在父类设置虚方法,也可以增加一个公开的getter和setter方法。
2、反射获取到的默认是是public公共的成员,例如MethodInfo obj = objType.GetMethod("FunA"); MethodInfo[] obj = objType.GetMethods(); 。但可以加上BindingFlags类型的参数:BindingFlags.NonPublic | BindingFlags.Instance,就能获取非公共的成员了,包括private私有的等。BindingFlags的使用有两点需要注意:
(1)BindingFlags.IgnoreCase 需要与 BindingFlags.Public 和 BindingFlags.Instance 一起用才会产生效果。
(2)对BindingFlags参数赋值后,为了获取返回值,必须指定 BindingFlags.Instance 或 BindingFlags.Static。
3、利用反射机制访问变量和方法的Java核心代码如下:
using System;
using System.Reflection;
void analytical()
{
// 指明当前对象
object obj = new SonClass();
// 获取对象的类型
Type type = obj.GetType();
// 对象的父类类型
type = type.BaseType; //如果obj=new ParentClass();这里就不需要了
//字段绑定标志
BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
// 获取type 中的 私有变量a
FieldInfo ff = type.GetField("a", flag);
// 读取变量值
object value = ff.GetValue(obj);
// 给变量赋值
ff.SetValue(obj, 123);
//获取对象的私有方法print
MethodInfo mf = type.GetMethod("printPr", flag);
// 实现对象中的方法
mf.Invoke(obj, null);
}
4、“用反射的方式获取父类中的所有属性和方法”这篇文章列举了一个封装好大部分功能的实例,实践是可参考其中的写法和注意事项。
5、unity中,Start()、Update()等方法在函数里是私有的,也不存在于monoBehaviour中,因此这些方法也是unity引擎使用反射来调用的。原因在于,并非所有的MonoBehaviour都需要Update(或Start,Awake等等,下同)。Unity会维护一个需要Update等的Behaviour列表,藉此避免进行空的虚函数调用,提高性能。平时代码里不用的空函数也删掉。
6、Unity使用这种事件机制的根本原因是出于对灵活性的考虑。Unity采用组件式设计,触发一个事件,需要通知到相应gameobject的所有组件。如果使用多态来实现,则必须假设所有组件都派生自包含此事件的基类,或者筛选出派生自此基类的组件逐一通知。这样一来是麻烦,二来则容易带来复杂的继承关系,与组件式这种倡导用聚合代替继承的设计从理念上就是相悖的。另一方面的原因则是为了跟JS保持一致性。这种事件机制对于JS这种动态类型语言来说是浑然天成的。
7、这种设计最大的缺陷在于事件名通过字符串耦合,如此一来,完全绕开了编译期静态检查,无法为事件调用的正确性提供保障;在复杂的系统里,也可能因为事件重名而导致bug。
8、unity其中一段源码:
inline void MonoBehaviour::Start ()
{
....
method = m_Methods[MonoScriptCache::kCoroutineStart];
if (method)
InvokeMethodOrCoroutineChecked (method, SCRIPTING_NULL);
}
双冒号::用于在类外定义类中函数或调用全局函数