利用反射机制访问父类私有变量和属性

参考文章:

子类用反射可以访问父类中的私有成员变量及方法

C#如何通过反射调用父类的私有方法

用反射的方式获取父类中的所有属性和方法

(来自知乎)Unity反射机制的理解

反射中BindingFlags的值



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);
}
双冒号::用于在类外定义类中函数或调用全局函数




















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值