private ObjectCheck genChecker(Type type) { ObjectCheck fixTypeCheck = (RealStatePtr L, int idx) => { if (LuaAPI.lua_type(L, idx) == LuaTypes.LUA_TUSERDATA) { object obj = translator.SafeGetCSObj(L, idx); if (obj != null) { return(type.IsAssignableFrom(obj.GetType())); } else { Type type_of_obj = translator.GetTypeOf(L, idx); if (type_of_obj != null) { return(type.IsAssignableFrom(type_of_obj)); } } } return(false); }; if (!type.IsAbstract() && typeof(Delegate).IsAssignableFrom(type)) { return((RealStatePtr L, int idx) => { return LuaAPI.lua_isnil(L, idx) || LuaAPI.lua_isfunction(L, idx) || fixTypeCheck(L, idx); }); } else if (type.IsEnum()) { return(fixTypeCheck); } else if (type.IsInterface()) { return((RealStatePtr L, int idx) => { return LuaAPI.lua_isnil(L, idx) || LuaAPI.lua_istable(L, idx) || fixTypeCheck(L, idx); }); } else { if ((type.IsClass() && type.GetConstructor(System.Type.EmptyTypes) != null)) //class has default construtor { return((RealStatePtr L, int idx) => { return LuaAPI.lua_isnil(L, idx) || LuaAPI.lua_istable(L, idx) || fixTypeCheck(L, idx); }); } else if (type.IsValueType()) { return((RealStatePtr L, int idx) => { return LuaAPI.lua_istable(L, idx) || fixTypeCheck(L, idx); }); } else if (type.IsArray) { return((RealStatePtr L, int idx) => { return LuaAPI.lua_isnil(L, idx) || LuaAPI.lua_istable(L, idx) || fixTypeCheck(L, idx); }); } else { return((RealStatePtr L, int idx) => { return LuaAPI.lua_isnil(L, idx) || fixTypeCheck(L, idx); }); } } }
private ObjectCast genCaster(Type type) { ObjectCast fixTypeGetter = (RealStatePtr L, int idx, object target) => { if (LuaAPI.lua_type(L, idx) == LuaTypes.LUA_TUSERDATA) { object obj = translator.SafeGetCSObj(L, idx); return((obj != null && type.IsAssignableFrom(obj.GetType())) ? obj : null); } return(null); }; if (typeof(Delegate).IsAssignableFrom(type)) { return((RealStatePtr L, int idx, object target) => { object obj = fixTypeGetter(L, idx, target); if (obj != null) { return obj; } if (!LuaAPI.lua_isfunction(L, idx)) { return null; } return translator.CreateDelegateBridge(L, type, idx); }); } else if (type.IsInterface()) { return((RealStatePtr L, int idx, object target) => { object obj = fixTypeGetter(L, idx, target); if (obj != null) { return obj; } if (!LuaAPI.lua_istable(L, idx)) { return null; } return translator.CreateInterfaceBridge(L, type, idx); }); } else if (type.IsEnum()) { return((RealStatePtr L, int idx, object target) => { object obj = fixTypeGetter(L, idx, target); if (obj != null) { return obj; } LuaTypes lua_type = LuaAPI.lua_type(L, idx); if (lua_type == LuaTypes.LUA_TSTRING) { return Enum.Parse(type, LuaAPI.lua_tostring(L, idx)); } else if (lua_type == LuaTypes.LUA_TNUMBER) { return Enum.ToObject(type, LuaAPI.xlua_tointeger(L, idx)); } throw new InvalidCastException("invalid value for enum " + type); }); } else if (type.IsArray) { return((RealStatePtr L, int idx, object target) => { object obj = fixTypeGetter(L, idx, target); if (obj != null) { return obj; } if (!LuaAPI.lua_istable(L, idx)) { return null; } uint len = LuaAPI.xlua_objlen(L, idx); int n = LuaAPI.lua_gettop(L); idx = idx > 0 ? idx : LuaAPI.lua_gettop(L) + idx + 1;// abs of index Type et = type.GetElementType(); ObjectCast elementCaster = GetCaster(et); Array ary = target == null?Array.CreateInstance(et, (int)len) : target as Array; if (!LuaAPI.lua_checkstack(L, 1)) { throw new Exception("stack overflow while cast to Array"); } for (int i = 0; i < len; ++i) { LuaAPI.lua_pushnumber(L, i + 1); LuaAPI.lua_rawget(L, idx); if (et.IsPrimitive()) { if (!StaticLuaCallbacks.TryPrimitiveArraySet(type, L, ary, i, n + 1)) { ary.SetValue(elementCaster(L, n + 1, null), i); } } else { if (StaticLuaCallbacks.GenTryArraySetPtr == null || !StaticLuaCallbacks.GenTryArraySetPtr(type, L, translator, ary, i, n + 1)) { ary.SetValue(elementCaster(L, n + 1, null), i); } } LuaAPI.lua_pop(L, 1); } return ary; }); } else if (typeof(IList).IsAssignableFrom(type) && type.IsGenericType()) { Type elementType = type.GetGenericArguments()[0]; ObjectCast elementCaster = GetCaster(elementType); return((RealStatePtr L, int idx, object target) => { object obj = fixTypeGetter(L, idx, target); if (obj != null) { return obj; } if (!LuaAPI.lua_istable(L, idx)) { return null; } obj = target == null?Activator.CreateInstance(type) : target; int n = LuaAPI.lua_gettop(L); idx = idx > 0 ? idx : LuaAPI.lua_gettop(L) + idx + 1;// abs of index IList list = obj as IList; uint len = LuaAPI.xlua_objlen(L, idx); if (!LuaAPI.lua_checkstack(L, 1)) { throw new Exception("stack overflow while cast to IList"); } for (int i = 0; i < len; ++i) { LuaAPI.lua_pushnumber(L, i + 1); LuaAPI.lua_rawget(L, idx); if (i < list.Count && target != null) { if (translator.Assignable(L, n + 1, elementType)) { list[i] = elementCaster(L, n + 1, list[i]);; } } else { if (translator.Assignable(L, n + 1, elementType)) { list.Add(elementCaster(L, n + 1, null)); } } LuaAPI.lua_pop(L, 1); } return obj; }); } else if (typeof(IDictionary).IsAssignableFrom(type) && type.IsGenericType()) { Type keyType = type.GetGenericArguments()[0]; ObjectCast keyCaster = GetCaster(keyType); Type valueType = type.GetGenericArguments()[1]; ObjectCast valueCaster = GetCaster(valueType); return((RealStatePtr L, int idx, object target) => { object obj = fixTypeGetter(L, idx, target); if (obj != null) { return obj; } if (!LuaAPI.lua_istable(L, idx)) { return null; } IDictionary dic = (target == null ? Activator.CreateInstance(type) : target) as IDictionary; int n = LuaAPI.lua_gettop(L); idx = idx > 0 ? idx : LuaAPI.lua_gettop(L) + idx + 1;// abs of index LuaAPI.lua_pushnil(L); if (!LuaAPI.lua_checkstack(L, 1)) { throw new Exception("stack overflow while cast to IDictionary"); } while (LuaAPI.lua_next(L, idx) != 0) { if (translator.Assignable(L, n + 1, keyType) && translator.Assignable(L, n + 2, valueType)) { object k = keyCaster(L, n + 1, null); dic[k] = valueCaster(L, n + 2, !dic.Contains(k) ? null : dic[k]); } LuaAPI.lua_pop(L, 1); // removes value, keeps key for next iteration } return dic; }); } else if ((type.IsClass() && type.GetConstructor(System.Type.EmptyTypes) != null) || (type.IsValueType() && !type.IsEnum())) //class has default construtor { return((RealStatePtr L, int idx, object target) => { object obj = fixTypeGetter(L, idx, target); if (obj != null) { return obj; } if (!LuaAPI.lua_istable(L, idx)) { return null; } obj = target == null?Activator.CreateInstance(type) : target; int n = LuaAPI.lua_gettop(L); idx = idx > 0 ? idx : LuaAPI.lua_gettop(L) + idx + 1;// abs of index if (!LuaAPI.lua_checkstack(L, 1)) { throw new Exception("stack overflow while cast to " + type); } /*foreach (PropertyInfo prop in type.GetProperties()) * { * LuaAPI.xlua_pushasciistring(L, prop.Name); * LuaAPI.lua_rawget(L, idx); * if (!LuaAPI.lua_isnil(L, -1)) * { * try * { * prop.SetValue(obj, GetCaster(prop.PropertyType)(L, n + 1, * target == null || prop.PropertyType.IsPrimitive || prop.PropertyType == typeof(string) ? null : prop.GetValue(obj, null)), null); * } * catch (Exception e) * { * throw new Exception("exception in tran " + prop.Name + ", msg=" + e.Message); * } * } * LuaAPI.lua_pop(L, 1); * }*/ foreach (FieldInfo field in type.GetFields()) { LuaAPI.xlua_pushasciistring(L, field.Name); LuaAPI.lua_rawget(L, idx); if (!LuaAPI.lua_isnil(L, -1)) { try { field.SetValue(obj, GetCaster(field.FieldType)(L, n + 1, target == null || field.FieldType.IsPrimitive() || field.FieldType == typeof(string) ? null : field.GetValue(obj))); } catch (Exception e) { throw new Exception("exception in tran " + field.Name + ", msg=" + e.Message); } } LuaAPI.lua_pop(L, 1); } return obj; }); } else { return(fixTypeGetter); } }
private bool luaFunctionCheck(RealStatePtr L, int idx) { return(LuaAPI.lua_isnil(L, idx) || LuaAPI.lua_isfunction(L, idx) || (LuaAPI.lua_type(L, idx) == LuaTypes.LUA_TUSERDATA && translator.SafeGetCSObj(L, idx) is LuaFunction)); }
object InvokeLua.ICalc.this[int index] { get { #if THREAD_SAFE || HOTFIX_ENABLE lock (luaEnv.luaEnvLock) { #endif RealStatePtr L = luaEnv.L; int err_func = LuaAPI.load_error_func(L, luaEnv.errorFuncRef); ObjectTranslator translator = luaEnv.translator; LuaAPI.lua_getref(L, luaReference); LuaAPI.xlua_pushasciistring(L, "get_Item"); if (0 != LuaAPI.xlua_pgettable(L, -2)) { luaEnv.ThrowExceptionFromError(err_func - 1); } if (!LuaAPI.lua_isfunction(L, -1)) { LuaAPI.xlua_pushasciistring(L, "no such function get_Item"); luaEnv.ThrowExceptionFromError(err_func - 1); } LuaAPI.lua_pushvalue(L, -2); LuaAPI.lua_remove(L, -3); LuaAPI.xlua_pushinteger(L, index); int __gen_error = LuaAPI.lua_pcall(L, 2, 1, err_func); if (__gen_error != 0) { luaEnv.ThrowExceptionFromError(err_func - 1); } object __gen_ret = translator.GetObject(L, err_func + 1, typeof(object)); LuaAPI.lua_settop(L, err_func - 1); return(__gen_ret); #if THREAD_SAFE || HOTFIX_ENABLE } #endif } set { #if THREAD_SAFE || HOTFIX_ENABLE lock (luaEnv.luaEnvLock) { #endif RealStatePtr L = luaEnv.L; int err_func = LuaAPI.load_error_func(L, luaEnv.errorFuncRef); ObjectTranslator translator = luaEnv.translator; LuaAPI.lua_getref(L, luaReference); LuaAPI.xlua_pushasciistring(L, "set_Item"); if (0 != LuaAPI.xlua_pgettable(L, -2)) { luaEnv.ThrowExceptionFromError(err_func - 1); } if (!LuaAPI.lua_isfunction(L, -1)) { LuaAPI.xlua_pushasciistring(L, "no such function set_Item"); luaEnv.ThrowExceptionFromError(err_func - 1); } LuaAPI.lua_pushvalue(L, -2); LuaAPI.lua_remove(L, -3); LuaAPI.xlua_pushinteger(L, index); translator.PushAny(L, value); int __gen_error = LuaAPI.lua_pcall(L, 3, 0, err_func); if (__gen_error != 0) { luaEnv.ThrowExceptionFromError(err_func - 1); } LuaAPI.lua_settop(L, err_func - 1); #if THREAD_SAFE || HOTFIX_ENABLE } #endif } }