diff --git a/Assets/XLua/Doc/XLua_API.md b/Assets/XLua/Doc/XLua_API.md index dccc4e211d14e6bd8e74be944c3ca4fb76d5352d..5e9fae5d3c9ce568b7495b123b83ed89318750e8 100644 --- a/Assets/XLua/Doc/XLua_API.md +++ b/Assets/XLua/Doc/XLua_API.md @@ -219,6 +219,31 @@ 描述: 让一个类的私有字段,属性,方法等可用 +例子: + + xlua.private_accessible(CS.UnityEngine.GameObject) + +#### xlua.get_generic_method +描述: + + 获取一个泛型方法 +例子: + +~~~lua +local foo_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Foo') +local bar_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Bar') + +local foo = foo_generic(CS.System.Int32, CS.System.Double) +local bar = bar_generic(CS.System.Double, CS.UnityEngine.GameObject) + +-- call instance method +local o = CS.GetGenericMethodTest() +local ret = foo(o, 1, 2) +print(ret) + +-- call static method +bar(2, nil) +~~~ #### cast函数 @@ -226,7 +251,7 @@ 指明以特定的接口访问对象,这在实现类无法访问的时候(比如internal修饰)很有用,这时可以这么来(假设下面的calc对象实现了C#的PerformentTest.ICalc接口) -例如: +例子: cast(calc, typeof(CS.PerformentTest.ICalc)) diff --git a/Assets/XLua/Doc/faq.md b/Assets/XLua/Doc/faq.md index 24b2442abbc6bcf4db4599187ee29b9ab2fa27a5..bc14450bf99ce721614b900a4c1da94c17ecfe6d 100644 --- a/Assets/XLua/Doc/faq.md +++ b/Assets/XLua/Doc/faq.md @@ -154,6 +154,47 @@ go:GetButton().onClick:AddListener(function() end) ``` +如果xlua版本大于2.1.12的话,新增反射调用泛型方法的支持,比如对于这么个C#类型: +```csharp +public class GetGenericMethodTest +{ + int a = 100; + public int Foo(T1 p1, T2 p2) + { + Debug.Log(typeof(T1)); + Debug.Log(typeof(T2)); + Debug.Log(p1); + Debug.Log(p2); + return a; + } + + public static void Bar(T1 p1, T2 p2) + { + Debug.Log(typeof(T1)); + Debug.Log(typeof(T2)); + Debug.Log(p1); + Debug.Log(p2); + } +} +``` +在lua那这么调用: +```lua +local foo_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Foo') +local bar_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Bar') + +local foo = foo_generic(CS.System.Int32, CS.System.Double) +local bar = bar_generic(CS.System.Double, CS.UnityEngine.GameObject) + +-- call instance method +local o = CS.GetGenericMethodTest() +local ret = foo(o, 1, 2) +print(ret) + +-- call static method +bar(2, nil) +``` + + ## 支持lua调用C#重载函数吗? 支持,但没有C#端支持的那么完善,比如重载方法void Foo(int a)和void Foo(short a),由于int和short都对应lua的number,是没法根据参数判断调用的是哪个重载。这时你可以借助扩展方法来为其中一个起一个别名。 diff --git a/Assets/XLua/Src/ObjectTranslator.cs b/Assets/XLua/Src/ObjectTranslator.cs index 5bd53caa80c602e8aa1286d49e7f36abd0f48f09..3bfc103d4830fbe3d2746a3ed661b381e9ad0c1f 100644 --- a/Assets/XLua/Src/ObjectTranslator.cs +++ b/Assets/XLua/Src/ObjectTranslator.cs @@ -605,6 +605,9 @@ namespace XLua LuaAPI.xlua_pushasciistring(L, "tofunction"); LuaAPI.lua_pushstdcallcfunction(L, StaticLuaCallbacks.ToFunction); LuaAPI.lua_rawset(L, -3); + LuaAPI.xlua_pushasciistring(L, "get_generic_method"); + LuaAPI.lua_pushstdcallcfunction(L, StaticLuaCallbacks.GetGenericMethod); + LuaAPI.lua_rawset(L, -3); LuaAPI.xlua_pushasciistring(L, "release"); LuaAPI.lua_pushstdcallcfunction(L, StaticLuaCallbacks.ReleaseCsObject); LuaAPI.lua_rawset(L, -3); diff --git a/Assets/XLua/Src/StaticLuaCallbacks.cs b/Assets/XLua/Src/StaticLuaCallbacks.cs index 3a02079c9f699af3f1edc7ae3f1444be4532430e..b3a18765ef538805f7159f3bf60c1692d8b8e73a 100644 --- a/Assets/XLua/Src/StaticLuaCallbacks.cs +++ b/Assets/XLua/Src/StaticLuaCallbacks.cs @@ -1089,6 +1089,85 @@ namespace XLua } } + [MonoPInvokeCallback(typeof(LuaCSFunction))] + public static int GenericMethodWraper(RealStatePtr L) + { + try + { + ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); + var genericMethod = translator.GetByType(L, LuaAPI.xlua_upvalueindex(1)); + int n = LuaAPI.lua_gettop(L); + Type[] typeArguments = new Type[n]; + for(int i = 0; i < n; i++) + { + Type type = getType(L, translator, i + 1); + if (type == null) + { + return LuaAPI.luaL_error(L, "param #" + (i + 1) + " is not a type"); + } + typeArguments[i] = type; + } + var method = genericMethod.MakeGenericMethod(typeArguments); + translator.PushFixCSFunction(L, + new LuaCSFunction(translator.methodWrapsCache._GenMethodWrap(method.DeclaringType, method.Name, new MethodBase[] { method }).Call)); + return 1; + } + catch (Exception e) + { + return LuaAPI.luaL_error(L, "c# exception in GenericMethodWraper: " + e); + } + } + + [MonoPInvokeCallback(typeof(LuaCSFunction))] + public static int GetGenericMethod(RealStatePtr L) + { + try + { + ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); + Type type = getType(L, translator, 1); + if (type == null) + { + return LuaAPI.luaL_error(L, "xlua.get_generic_method, can not find c# type"); + } + string methodName = LuaAPI.lua_tostring(L, 2); + if (string.IsNullOrEmpty(methodName)) + { + return LuaAPI.luaL_error(L, "xlua.get_generic_method, #2 param need a string"); + } + System.Collections.Generic.List matchMethods = new System.Collections.Generic.List(); + var allMethods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + for(int i = 0; i < allMethods.Length; i++) + { + var method = allMethods[i]; + if (method.Name == methodName && method.IsGenericMethodDefinition) + { + matchMethods.Add(method); + } + } + + int methodIdx = 0; + + if (matchMethods.Count == 0) + { + LuaAPI.lua_pushnil(L); + } + else + { + if (LuaAPI.lua_isinteger(L, 3)) + { + methodIdx = LuaAPI.xlua_tointeger(L, 3); + } + translator.PushAny(L, matchMethods[methodIdx]); + LuaAPI.lua_pushstdcallcfunction(L, GenericMethodWraper, 1); + } + } + catch (Exception e) + { + return LuaAPI.luaL_error(L, "c# exception in xlua.get_generic_method: " + e); + } + return 1; + } + [MonoPInvokeCallback(typeof(LuaCSFunction))] public static int ReleaseCsObject(RealStatePtr L) {