/// <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>()); }
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(); }