Esempio n. 1
0
        /// <summary>
        /// 创建指定 <paramref name="propertyInfo"/> 的动态属性获取器。
        /// </summary>
        /// <param name="propertyInfo">属性的元数据。</param>
        /// <param name="declaringType">声明该成员的类。</param>
        /// <returns>返回一个绑定到实例属性获取器的委托。</returns>
        protected override DynamicGetMemberHandler CreateHandler(PropertyInfo propertyInfo, Type declaringType)
        {
            var methodInfo = propertyInfo.GetGetMethod(true);

            EmitHelper emit = new EmitHelper(string.Empty,
                                             Types.Object,
                                             new Type[1] {
                Types.Object
            },
                                             declaringType,
                                             SkipVisibility,
                                             false);//- 为什么这里不使用 OwnerType 而使用 member.DeclaringType,主要是考虑到泛型:<object>

            if (!methodInfo.IsStatic)
            {
                emit.LoadThis(methodInfo);  //- 非静态,取出实例
            }
            emit.Call(methodInfo);
            emit.TryBox(methodInfo.ReturnType);
            emit.Return();
            return(emit.CreateDelegate <DynamicGetMemberHandler>());
        }
        /// <summary>
        /// 创建指定 <paramref name="methodInfo"/> 的动态方法。
        /// </summary>
        /// <param name="methodInfo">方法的元数据。</param>
        /// <param name="declaringType">声明该成员的类。</param>
        /// <returns>返回一个绑定到实例方法的委托。</returns>
        protected override DynamicMethodHandler CreateHandler(MethodInfo methodInfo, Type declaringType)
        {
            Type returnType = methodInfo.ReturnType;                      //- 方法的返回类型

            ParameterInfo[] parameterInfos = methodInfo.GetParameters();  //- 方法的参数集合
            int             paramterLength = parameterInfos.Length;

            EmitHelper emit = new EmitHelper(string.Empty,
                                             Types.Object,
                                             new Type[2] {
                Types.Object, Types.ObjectArray
            },
                                             declaringType,
                                             SkipVisibility,
                                             false);//- 为什么这里不使用 OwnerType 而使用 member.DeclaringType,主要是考虑到泛型:<object>

            Type[] paramTypes = new Type[paramterLength];

            LocalBuilder[] locals = new LocalBuilder[paramterLength];

            for (int i = 0; i < paramterLength; i++)
            {
                if (parameterInfos[i].ParameterType.IsByRef)
                {
                    paramTypes[i] = parameterInfos[i].ParameterType.GetElementType();
                }
                else
                {
                    paramTypes[i] = parameterInfos[i].ParameterType;
                }

                locals[i] = emit.DeclareLocal(paramTypes[i]);
                emit.LoadArgument(1);       //- 取出参数1 也就是 object[]
                emit.LoadConstant(i);       //- 指定索引号 —— 0
                emit.LoadRefElement();      //- 取出索引元素 object[0]
                emit.CastTo(paramTypes[i]); //- 类型转换,从 object 到指定参数类型。
                emit.StoreLocal(locals[i]);
            }

            if (!methodInfo.IsStatic)
            {
                emit.LoadThis(methodInfo);  //- 非静态,取出实例
                //emit.CastTo(member.DeclaringType);
            }

            for (int i = 0; i < paramterLength; i++)
            {   //- 取出所有 method 函数的参数
                if (parameterInfos[i].ParameterType.IsByRef)
                {
                    emit.LoadLocalBySpecific(locals[i]);
                }
                else
                {
                    emit.LoadLocal(locals[i]);
                }
            }

            emit.Call(methodInfo);

            if (returnType == typeof(void))
            {
                emit.LoadNull();
            }
            else
            {
                emit.TryBox(returnType);
            }

            for (int i = 0; i < paramterLength; i++)
            {
                if (parameterInfos[i].ParameterType.IsByRef)
                {
                    emit.LoadArgument(1);               //- 取出参数1 也就是 object[]
                    emit.LoadConstant(i);               //- 指定索引号 —— 0
                    emit.LoadLocal(locals[i]);          //- 加载指定索引的数组元素
                    emit.TryBox(locals[i].LocalType);   //- 尝试装箱  paramTypes[i]
                    emit.StoreLocalByRef();             //- 赋值给 ref 或  out
                }
            }
            emit.Return();
            return(emit.CreateDelegate <DynamicMethodHandler>());
        }
Esempio n. 3
0
        private static void EmitInvoker(EmitHelper emit, MethodInfo method, int?argc, bool setter)
        {
            var parameters = method.GetParameters();
            var methodArgC = parameters.Length;

            if (!argc.HasValue)
            {
                EmitThrowIfArgumentCountMismatch(emit, methodArgC);
                argc = methodArgC;
            }

            emit.LdArg(retvalArgIndex);

            // instance method
            if (!method.IsStatic)
            {
                emit.LdArg(objArgIndex);
            }

            // prepare arguments
            for (var i = 0; i < parameters.Length; i++)
            {
                var parameter = parameters[i];

                if (i < argc.Value)
                {
                    var changeTypeMethod = CefConvert.GetChangeTypeMethod(typeof(cef_v8value_t *), parameter.ParameterType);

                    EmitLdV8Argument(emit, i);
                    emit.Call(changeTypeMethod);
                }
                else
                {
                    // push default arg
                    if (!parameter.IsOptional)
                    {
                        throw new JSBindingException("MethodInvoker compilation error.");
                    }

                    EmitLdRawDefaultValue(emit, parameter.RawDefaultValue);
                }
            }

            // call target method
            if (method.IsStatic)
            {
                emit.Call(method);
            }
            else
            {
                emit.CallVirt(method);
            }


            if (method.ReturnType == typeof(void))
            {
                // If method is setter, then it can be called with retval == null from V8Accessor.
                if (setter)
                {
                    var returnValueLabel = emit.DefineLabel();

                    emit.Dup()
                    .BrTrueS(returnValueLabel)
                    .Pop()
                    .Ret()
                    .MarkLabel(returnValueLabel);
                    ;
                }

                if (ForceVoidToUndefined)
                {
                    emit.Call(createUndefinedNativeV8ValueMethod);
                }
                else
                {
                    emit.LdNull();
                }
            }
            else
            {
                // convert return value
                var retValchangeTypeMethod = CefConvert.GetChangeTypeMethod(method.ReturnType, typeof(cef_v8value_t *));
                emit.Call(retValchangeTypeMethod);
            }

            // store result at retval
            emit.StIndI();

            // return
            emit.Ret();
        }
        private static void EmitInvoker(EmitHelper emit, MethodInfo method, int? argc, bool setter)
        {
            var parameters = method.GetParameters();
            var methodArgC = parameters.Length;

            if (!argc.HasValue)
            {
                EmitThrowIfArgumentCountMismatch(emit, methodArgC);
                argc = methodArgC;
            }

            emit.LdArg(retvalArgIndex);

            // instance method
            if (!method.IsStatic)
            {
                emit.LdArg(objArgIndex);
            }

            // prepare arguments
            for (var i = 0; i < parameters.Length; i++)
            {
                var parameter = parameters[i];

                if (i < argc.Value)
                {
                    var changeTypeMethod = CefConvert.GetChangeTypeMethod(typeof(cef_v8value_t*), parameter.ParameterType);

                    EmitLdV8Argument(emit, i);
                    emit.Call(changeTypeMethod);
                }
                else
                {
                    // push default arg
                    if (!parameter.IsOptional) throw new JSBindingException("MethodInvoker compilation error.");

                    EmitLdRawDefaultValue(emit, parameter.RawDefaultValue);
                }
            }

            // call target method
            if (method.IsStatic)
            {
                emit.Call(method);
            }
            else
            {
                emit.CallVirt(method);
            }

            if (method.ReturnType == typeof(void))
            {
                // If method is setter, then it can be called with retval == null from V8Accessor.
                if (setter)
                {
                    var returnValueLabel = emit.DefineLabel();

                    emit.Dup()
                        .BrTrueS(returnValueLabel)
                        .Pop()
                        .Ret()
                        .MarkLabel(returnValueLabel);
                    ;
                }

                if (ForceVoidToUndefined)
                {
                    emit.Call(createUndefinedNativeV8ValueMethod);
                }
                else
                {
                    emit.LdNull();
                }
            }
            else
            {
                // convert return value
                var retValchangeTypeMethod = CefConvert.GetChangeTypeMethod(method.ReturnType, typeof(cef_v8value_t*));
                emit.Call(retValchangeTypeMethod);
            }

            // store result at retval
            emit.StIndI();

            // return
            emit.Ret();
        }