예제 #1
0
        /*
         * __call metafunction of type references. Searches for and calls
         * a constructor for the type. Returns nil if the constructor is not
         * found or if the arguments are invalid. Throws an error if the constructor
         * generates an exception.
         */
        private int callConstructor(ILuaState luaState)
        {
            MethodCache validConstructor = new MethodCache();
            IReflect    klass;
            object      obj = translator.getRawNetObject(luaState, 1);

            if (obj == null || !(obj is IReflect))
            {
                translator.throwError(luaState, "trying to call constructor on an invalid type reference");
                LuaDLL.lua_pushnil(luaState);
                return(1);
            }
            else
            {
                klass = (IReflect)obj;
            }
            LuaDLL.lua_remove(luaState, 1);
            ConstructorInfo[] constructors = klass.UnderlyingSystemType.GetConstructors();
            foreach (ConstructorInfo constructor in constructors)
            {
                bool isConstructor = matchParameters(luaState, constructor, ref validConstructor);
                if (isConstructor)
                {
                    try
                    {
                        translator.push(luaState, constructor.Invoke(validConstructor.args));
                    }
                    catch (TargetInvocationException e)
                    {
                        ThrowError(luaState, e);
                        LuaDLL.lua_pushnil(luaState);
                    }
                    catch
                    {
                        LuaDLL.lua_pushnil(luaState);
                    }
                    return(1);
                }
            }

            string constructorName = (constructors.Length == 0) ? "unknown" : constructors[0].Name;

            translator.throwError(luaState, String.Format("{0} does not contain constructor({1}) argument match",
                                                          klass.UnderlyingSystemType,
                                                          constructorName));
            LuaDLL.lua_pushnil(luaState);
            return(1);
        }
예제 #2
0
        /*
         * Matches a method against its arguments in the Lua stack. Returns
         * if the match was succesful. It it was also returns the information
         * necessary to invoke the method.
         */
        internal bool matchParameters(ILuaState luaState, MethodBase method, ref MethodCache methodCache)
        {
            ExtractValue extractValue;
            bool         isMethod = true;

            ParameterInfo[]   paramInfo       = method.GetParameters();
            int               currentLuaParam = 1;
            int               nLuaParams      = LuaDLL.lua_gettop(luaState);
            ArrayList         paramList       = new ArrayList();
            List <int>        outList         = new List <int>();
            List <MethodArgs> argTypes        = new List <MethodArgs>();

            foreach (ParameterInfo currentNetParam in paramInfo)
            {
                if (!currentNetParam.IsIn && currentNetParam.IsOut)  // Skips out params
                {
                    outList.Add(paramList.Add(null));
                }
                else if (currentLuaParam > nLuaParams) // Adds optional parameters
                {
                    if (currentNetParam.IsOptional)
                    {
                        paramList.Add(currentNetParam.DefaultValue);
                    }
                    else
                    {
                        isMethod = false;
                        break;
                    }
                }
                else if (_IsTypeCorrect(luaState, currentLuaParam, currentNetParam, out extractValue))  // Type checking
                {
                    int index = paramList.Add(extractValue(luaState, currentLuaParam));

                    MethodArgs methodArg = new MethodArgs();
                    methodArg.index        = index;
                    methodArg.extractValue = extractValue;
                    argTypes.Add(methodArg);

                    if (currentNetParam.ParameterType.IsByRef)
                    {
                        outList.Add(index);
                    }
                    currentLuaParam++;
                }  // Type does not match, ignore if the parameter is optional
                else if (_IsParamsArray(luaState, currentLuaParam, currentNetParam, out extractValue))
                {
                    object luaParamValue = extractValue(luaState, currentLuaParam);

                    Type paramArrayType = currentNetParam.ParameterType.GetElementType();

                    Array paramArray;

                    if (luaParamValue is LuaTable)
                    {
                        LuaTable table = (LuaTable)luaParamValue;
                        IDictionaryEnumerator tableEnumerator = table.GetEnumerator();

                        paramArray = Array.CreateInstance(paramArrayType, table.Values.Count);

                        tableEnumerator.Reset();

                        int paramArrayIndex = 0;

                        while (tableEnumerator.MoveNext())
                        {
                            paramArray.SetValue(Convert.ChangeType(tableEnumerator.Value, currentNetParam.ParameterType.GetElementType()), paramArrayIndex);
                            paramArrayIndex++;
                        }
                    }
                    else
                    {
                        paramArray = Array.CreateInstance(paramArrayType, 1);
                        paramArray.SetValue(luaParamValue, 0);
                    }

                    int index = paramList.Add(paramArray);

                    MethodArgs methodArg = new MethodArgs();
                    methodArg.index           = index;
                    methodArg.extractValue    = extractValue;
                    methodArg.isParamsArray   = true;
                    methodArg.paramsArrayType = paramArrayType;
                    argTypes.Add(methodArg);

                    currentLuaParam++;
                }
                else if (currentNetParam.IsOptional)
                {
                    paramList.Add(currentNetParam.DefaultValue);
                }
                else  // No match
                {
                    isMethod = false;
                    break;
                }
            }
            if (currentLuaParam != nLuaParams + 1) // Number of parameters does not match
            {
                isMethod = false;
            }
            if (isMethod)
            {
                methodCache.args         = paramList.ToArray();
                methodCache.cachedMethod = method;
                methodCache.outList      = outList.ToArray();
                methodCache.argTypes     = argTypes.ToArray();
            }
            return(isMethod);
        }
예제 #3
0
 /*
  * Checks if the method matches the arguments in the Lua stack, getting
  * the arguments if it does.
  */
 internal bool matchParameters(ILuaState luaState, MethodBase method, ref MethodCache methodCache)
 {
     return(metaFunctions.matchParameters(luaState, method, ref methodCache));
 }