|
引言:
为了方便在没有wrap的情况下,fix c#的一些bug,在不能使用动态反射的情况下(ios不支持,具体不支持哪些API,我也不知道~~尴尬!),只好研究下tolua的静态反射功能。以下提到的反射,均为静态反射。
正文:
接下来会从几个方面来写这篇文章
1.tolua导出的System_TypeWrap.cs中为什么没有GetMethod等一系列反射方法?
解释:
1)既然没有,怎么生成?
打开ToLua_System_Type.cs脚本,可以看到很多[NoToLuaAttribute]修饰的方法。[NoToLuaAttribute]这个特性是用来屏蔽导出wrap的,删除(注释)后,再次点击unity菜单栏 lua菜单的Gen BaseType ,可重新生成完整的System_TypeWrap.cs
2)为什么会屏蔽?
tolua自己封装了一套相对更优(查找速度?)的反射方法组,在Tolua/Reflection/目录下的
LuaConstructor.cs、LuaField.cs、LuaMethod.cs、LuaProperty.cs、LuaReflection.cs
2.怎么使用?
ToLua/Examples/22_Reflection 的示例中,已经演示了大部分的使用方法,参见TestReflection.cs
对于私有的一些东西,示例中没有说明。这里补充一下
lua脚本- print('------------------tolua自带反射测试----------------------')
- --lua自带反射测试
- require 'tolua.reflection'
- tolua.loadassembly('Assembly-CSharp')
- --为了省事,全部与一遍
- local bitor = bit.bor(0,1,2,4,8,16,32,64,256,512,1024,2048,4096,8192,16384,32768)
- --上面每个与值的枚举
- --local BindingFlags = require 'System.Reflection.BindingFlags'
- local t = typeof('BoTest2')
- --创建对象
- local obj = tolua.createinstance(t)
- --公有静态方法
- local func = tolua.getmethod(t, 'BoTest2_public_static_int')
- print(func:Call())
- func:Destroy()
- func = nil
- --公有静态带参数方法
- local func = tolua.getmethod(t, 'BoTest2_public_static_int_arg',typeof('System.Int32'))
- print(func:Call(1))
- func:Destroy()
- func = nil
- --公有方法
- local func = tolua.getmethod(t, 'BoTest2_public_int')
- print(func:Call(obj) )
- func:Destroy()
- func = nil
- --公有带参数方法
- local func = tolua.getmethod(t, 'BoTest2_public_int_arg',typeof('System.Int32'))
- print(func:Call(obj,2))
- func:Destroy()
- func = nil
- --私有静态方法
- local func = tolua.gettypemethod(t, 'BoTest2_static_int',bitor)
- print(func:Call())
- func:Destroy()
- func = nil
- --私有方法
- local func = tolua.gettypemethod(t, 'BoTest2_int',bitor)
- print(func:Call(obj))
- func:Destroy()
- func = nil
-
- --公有字段
- local field = tolua.getfield(t, 'public_int')
- field:Set(obj, 5)
- print(field:Get(obj))
- field:Destroy()
- --私有字段
- local field = tolua.getfield(t, 'private_int',bitor)
- field:Set(obj, 6)
- print(field:Get(obj))
- field:Destroy()
- --公有属性
- local property = tolua.getproperty(t, 'public_int_set_get')
- property:Set(obj, 7, null)
- print(property:Get(obj, null))
- property:Destroy()
- --私有属性
- local property = tolua.getproperty(t, 'private_int_set_get',bitor)
- property:Set(obj, 8, null)
- print(property:Get(obj, null))
- property:Destroy()
- --枚举,这里主要说明枚举怎么用typeof
- local t = typeof('TestEnumOut')
- local t = typeof('BoTest2+TestEnumIn')--这里用 ‘+’来代替‘.’
复制代码 C#脚本- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class BoTest2 {
- //私有变量
- private int private_int;
- public int public_int;
- static int static_int;
- public static int public_static_int;
- private int _public_int_set_get;
- public int public_int_set_get { set { _public_int_set_get = value; } get { return _public_int_set_get; } }
- private int private_int_set_get { set { _public_int_set_get = value; } get { return _public_int_set_get; } }
- //私有方法
- int BoTest2_int()
- {
- Debug.Log("BoTest2_int");
- return 1;
- }
-
- //私有静态方法
- static int BoTest2_static_int()
- {
- Debug.Log("BoTest2_static_int");
- return 1;
- }
- static int BoTest2_static_int_arg(int arg)
- {
- Debug.Log("BoTest2_static_int_arg");
- Debug.Log("arg:" + arg);
- return 1;
- }
- //公有方法
- public int BoTest2_public_int()
- {
- Debug.Log("BoTest2_public_int");
- return 1;
- }
- public int BoTest2_public_int_arg(int arg)
- {
- Debug.Log("BoTest2_public_int_arg");
- Debug.Log("arg:" + arg);
- return 1;
- }
- //公有静态方法
- public static int BoTest2_public_static_int()
- {
- Debug.Log("BoTest2_public_static_int");
- return 1;
- }
- public static int BoTest2_public_static_int_arg(int arg)
- {
- Debug.Log("BoTest2_public_static_int_arg");
- Debug.Log("arg:" + arg);
- return 1;
- }
- //类内部枚举
- public enum TestEnumIn
- {
- A,
- B,
- C
- }
- }
- //类外部枚举
- public enum TestEnumOut
- {
- A,
- B,
- C
- }
复制代码 全部的可用方法都能在LuaReflection.cs中找到,如下- public static void OpenLibs(IntPtr L)
- {
- LuaDLL.lua_getglobal(L, "tolua");
- LuaDLL.lua_pushstring(L, "findtype");
- LuaDLL.lua_pushcfunction(L, FindType);
- LuaDLL.lua_rawset(L, -3);
- LuaDLL.lua_pushstring(L, "loadassembly");
- LuaDLL.tolua_pushcfunction(L, LoadAssembly);
- LuaDLL.lua_rawset(L, -3);
- LuaDLL.lua_pushstring(L, "getmethod");
- LuaDLL.tolua_pushcfunction(L, GetMethod);
- LuaDLL.lua_rawset(L, -3);
- LuaDLL.lua_pushstring(L, "getconstructor");
- LuaDLL.tolua_pushcfunction(L, GetConstructor);
- LuaDLL.lua_rawset(L, -3);
- LuaDLL.lua_pushstring(L, "gettypemethod");
- LuaDLL.tolua_pushcfunction(L, GetTypeMethod);
- LuaDLL.lua_rawset(L, -3);
- LuaDLL.lua_pushstring(L, "getfield");
- LuaDLL.tolua_pushcfunction(L, GetField);
- LuaDLL.lua_rawset(L, -3);
- LuaDLL.lua_pushstring(L, "getproperty");
- LuaDLL.tolua_pushcfunction(L, GetProperty);
- LuaDLL.lua_rawset(L, -3);
- LuaDLL.lua_pushstring(L, "createinstance");
- LuaDLL.tolua_pushcfunction(L, CreateInstance);
- LuaDLL.lua_rawset(L, -3);
- LuaDLL.lua_pop(L, 1);
- LuaState state = LuaState.Get(L);
- state.BeginPreLoad();
- state.AddPreLoad("tolua.reflection", OpenReflectionLibs);
- state.EndPreLoad();
- }
复制代码 坑点:
1.自己生成了完整的System_TypeWrap.cs,直接使用C#的反射的一些方法,在传参数的时候会有坑,比如lua的number类型,在C# 中是double类型的,如果X方法的参数是int类型,你在调用的时候就会出错!
tolua来处理这个问题的地方列举一个(其他method等也有类似处理!)如下:
可以对比
System_Reflection_FieldInfoWrap.cs的SetValue方法和
LuaField.cs的Set方法- public int Set(IntPtr L)
- {
- try
- {
- int count = LuaDLL.lua_gettop(L);
- if (count == 3)
- {
- object arg0 = ToLua.CheckVarObject(L, 2, kclass);
- object arg1 = ToLua.ToVarObject(L, 3);
- //这里!!!可以对比System_Reflection_FieldInfoWrap.cs的SetValue方法
- if (arg1 != null) arg1 = TypeChecker.ChangeType(arg1, field.FieldType);
- field.SetValue(arg0, arg1);
- return 0;
- }
- else if (count == 6)
- {
- object arg0 = ToLua.CheckVarObject(L, 2, kclass);
- object arg1 = ToLua.ToVarObject(L, 3);
- if (arg1 != null) arg1 = TypeChecker.ChangeType(arg1, field.FieldType);
- BindingFlags arg2 = (BindingFlags)LuaDLL.luaL_checknumber(L, 4);
- Binder arg3 = (Binder)ToLua.CheckObject(L, 5, typeof(Binder));
- CultureInfo arg4 = (CultureInfo)ToLua.CheckObject(L, 6, typeof(CultureInfo));
- field.SetValue(arg0, arg1, arg2, arg3, arg4);
- return 0;
- }
- else
- {
- return LuaDLL.luaL_throw(L, "invalid arguments to method: LuaField.Set");
- }
- }
- catch (Exception e)
- {
- return LuaDLL.toluaL_exception(L, e);
- }
- }
复制代码 从这里,我猜想,tolua自己封装反射方法的原因很大也是由于这个!所以这里不推荐自己生成完整的System_TypeWrap.cs来做反射的相关功能!
使用技巧
1.对于MonoBehaviour类脚本。一般来言我们可以通过GetComponent(‘脚本名’)获取该脚本的对象,来实现获取改脚本内部变量方法的获取和调用。
2.对于1结合之前的挂载Lua组件LuaComponent特别好用!!!
https://blog.csdn.net/u010314160/article/details/81067750
文中观点,仅限本人理解,若有误,请留言指出!感谢! |
|