예제 #1
0
        static int MetaConstructFunctionInternal(lua_State L)
        {
            var typeObj = Lua.ObjectAtInternal(L, 1);

            Lua.Assert((typeObj != null && (typeObj is System.Type)), "Constructor needs type object.");

            var numArgs = Api.lua_gettop(L);

            int[] luaArgTypes = Lua.luaArgTypes_NoArgs;
            if (numArgs > 1)             // the first arg is class itself
            {
                luaArgTypes = new int[numArgs - 1];
                for (var i = 2; i <= numArgs; ++i)
                {
                    luaArgTypes[i - 2] = Api.lua_type(L, i);
                }
            }

            var type = (System.Type)typeObj;

            if (luaArgTypes == Lua.luaArgTypes_NoArgs && type.IsValueType)
            {
                var value = Activator.CreateInstance(type);
                Lua.PushObjectInternal(L, value);
                return(1);
            }

            var mangledName = Lua.CheckHost(L).Mangle("__ctor", luaArgTypes, invokingStaticMethod: true, argStart: 2);
            var mc          = Lua.GetMethodFromCache(type, mangledName);

            System.Reflection.ParameterInfo[] parameters = null;
            if (mc == null)
            {
                var constructors = type.GetConstructors();
                System.Reflection.MethodBase selected = null;
                int highScore = int.MinValue;
                List <Exception> pendingExceptions = null;
                for (var i = 0; i < constructors.Length; ++i)
                {
                    var method = constructors[i];
                    try
                    {
                        Lua.MatchingParameters(L, 2, method, luaArgTypes, ref highScore, ref selected, ref parameters);
                    }
                    catch (System.Reflection.AmbiguousMatchException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        if (pendingExceptions == null)
                        {
                            pendingExceptions = new List <Exception>();
                        }
                        pendingExceptions.Add(e);
                    }
                }
                if (selected != null)
                {
                    mc = Lua.CacheMethod(type, mangledName, selected, parameters);
                }
                else
                {
                    var additionalMessage = string.Empty;
                    if (pendingExceptions != null && pendingExceptions.Count > 0)
                    {
                        var sb = new System.Text.StringBuilder();
                        for (int i = 0; i < pendingExceptions.Count; ++i)
                        {
                            sb.AppendLine(pendingExceptions[i].Message);
                        }
                        additionalMessage = sb.ToString();
                    }
                    throw new Exception(string.Format("No proper constructor available, calling {0}\n{1}", Lua.GetLuaInvokingSigniture("ctor", luaArgTypes), additionalMessage));
                }
            }

            var ctor = (System.Reflection.ConstructorInfo)mc.method;

            IDisposable[] disposableArgs;
            var           args = Lua.ArgsFrom(L, mc.parameters, mc.variadicArg, 2, luaArgTypes.Length, out disposableArgs);

            Lua.PushObjectInternal(L, ctor.Invoke(args));
            if (disposableArgs != null)
            {
                foreach (var d in disposableArgs)
                {
                    if (d != null)
                    {
                        d.Dispose();
                    }
                }
            }
            return(1);
        }