コード例 #1
0
        // #lizard forgives
        public unsafe void Invoke(VirtualMachine virtualMachine, ref Call call, bool isInstantiate)
        {
            var managedStack = call.managedStack;
            var pushResult   = false;
            var args         = new object[paramCount];

            try
            {
                //virtualMachine._Info("method: " + method);
                Value *pArg = call.argumentBase;

                int paramStart = 0;

                if (hasThis && !isInstantiate)
                {
                    paramStart = 1;
                    pArg++;
                }

                for (int i = 0; i < paramCount; i++)
                {
                    if (!outFlags[i])
                    {
                        args[i] = EvaluationStackOperation.ToObject(call.evaluationStackBase, pArg, managedStack,
                                                                    rawTypes[i], virtualMachine);
                    }
                    //if (pArg->Type >= ValueType.Object)
                    //{
                    //    managedStack[pArg->Value1] = null;
                    //}
                    //if (method.Name == "Invoke" && method.DeclaringType.Name == "MethodBase")
                    //{
                    //    VirtualMachine._Info(i + " pArg->Type:" + pArg->Type);
                    //    VirtualMachine._Info(i + " args[i]:" + args[i]);
                    //    if (args[i] != null)
                    //    {
                    //        VirtualMachine._Info(i + " args[i]:" + args[i].GetHashCode());
                    //    }
                    //    VirtualMachine._Info(i + " args[i].GetType:" + (args[i] == null ?
                    //        "null" : args[i].GetType().ToString()));
                    //    if (i == 1 && args[i] is object[])
                    //    {
                    //        var objs = args[i] as object[];
                    //        for (int j = 0; j < objs.Length;j++)
                    //        {
                    //            VirtualMachine._Info("obj " + j + ": " + (objs[j] == null ?
                    //            "null" : objs[j].GetType().ToString()));
                    //        }
                    //    }
                    //}
                    pArg++;
                }

                object ret;

                if (isInstantiate || (method.IsConstructor && method.DeclaringType.IsValueType))
                {
                    ret = ctor.Invoke(args);//TODO: Delegate创建用Delegate.CreateDelegate
                }
                else
                {
                    object instance = null;
                    if (hasThis)
                    {
                        instance = EvaluationStackOperation.ToObject(call.evaluationStackBase, call.argumentBase,
                                                                     managedStack, method.DeclaringType, virtualMachine, false);
                    }
                    //Nullable仍然是值类型,只是新增了是否为null的标志位,仍然通过传地址的方式进行方法调用,
                    //但这在反射调用行不通,参数是object类型,boxing到object就是null,所以会触发
                    //“Non-static method requires a target”异常
                    //所以这只能特殊处理一下
                    if (isNullableHasValue)
                    {
                        ret = (instance != null);
                    }
                    else if (isNullableValue)
                    {
                        ret = instance;
                    }
                    else
                    {
                        ret = method.Invoke(instance, args);
                    }
                }

                for (int i = 0; i < paramCount; i++)
                {
                    if (refFlags[i])
                    {
                        call.UpdateReference(i + paramStart, args[i], virtualMachine, rawTypes[i]);
                    }
                }

                if (hasReturn || isInstantiate)
                {
                    if (method.IsConstructor && method.DeclaringType.IsValueType && !isInstantiate)
                    {
                        call.UpdateReference(0, ret, virtualMachine, method.DeclaringType);
                    }
                    else
                    {
                        call.PushObjectAsResult(ret, returnType);
                        pushResult = true;
                    }
                }
            }
            //catch (TargetInvocationException e)
            //{
            //    //VirtualMachine._Info("exception method: " + method + ", in " + method.DeclaringType + ", msg:"
            //        + e.InnerException);
            //    //for (int i = 0; i < paramCount; i++)
            //    //{
            //    //    VirtualMachine._Info("arg " + i + " type: " + (args[i] == null ? "null" : args[i].GetType()
            //    //        .ToString()) + " value: " + args[i]);
            //    //}
            //    if (e.InnerException is System.ArgumentException && args.Length == 2 && args[1] is object[])
            //    {
            //        //VirtualMachine._Info("exception method: " + method + ", in " + method.DeclaringType
            //        //    + ", msg:" + e.InnerException);
            //        if (instance is MethodBase)
            //        {
            //            MethodBase mb = instance as MethodBase;
            //            VirtualMachine._Info("exception method: " + mb + ", in " + mb.DeclaringType);
            //        }
            //        args = args[1] as object[];
            //        for (int i = 0; i < args.Length; i++)
            //        {
            //            VirtualMachine._Info("arg " + i + " type: " + (args[i] == null ?
            //            "null" : args[i].GetType().ToString()) + " value: " + args[i]);
            //        }
            //    }
            //    throw e;
            //}
            finally
            {
                //for (int i = 0; i < paramCount; i++)
                //{
                //    args[i] = null;
                //}
                Value *pArg = call.argumentBase;
                if (pushResult)
                {
                    pArg++;
                }
                for (int i = (pushResult ? 1 : 0); i < paramCount + ((hasThis && !isInstantiate) ? 1 : 0); i++)
                {
                    managedStack[pArg - call.evaluationStackBase] = null;
                    pArg++;
                }
            }
        }