public static unsafe InvokeFunc CreateInvokeDelegate(MethodBase method) { Debug.Assert(!method.ContainsGenericParameters); bool emitNew = method is RuntimeConstructorInfo; bool hasThis = !(emitNew || method.IsStatic); // The first parameter is unused but supports treating the DynamicMethod as an instance method which is slightly faster than a static. Type[] delegateParameters = new Type[3] { typeof(object), typeof(object), typeof(IntPtr *) }; string declaringTypeName = method.DeclaringType != null ? method.DeclaringType.Name + "." : string.Empty; var dm = new DynamicMethod( InvokeStubPrefix + declaringTypeName + method.Name, returnType: typeof(object), delegateParameters, restrictedSkipVisibility: true); ILGenerator il = dm.GetILGenerator(); // Handle instance methods. if (hasThis) { il.Emit(OpCodes.Ldarg_1); if (method.DeclaringType !.IsValueType) { il.Emit(OpCodes.Unbox, method.DeclaringType); } } // Push the arguments. ParameterInfo[] parameters = method.GetParametersNoCopy(); for (int i = 0; i < parameters.Length; i++) { il.Emit(OpCodes.Ldarg_2); if (i != 0) { il.Emit(OpCodes.Ldc_I4, i * IntPtr.Size); il.Emit(OpCodes.Add); } il.Emit(OpCodes.Call, Methods.ByReferenceOfByte_Value()); // This can be replaced by ldfld once byref fields are available in C# RuntimeType parameterType = (RuntimeType)parameters[i].ParameterType; if (!parameterType.IsByRef) { il.Emit(OpCodes.Ldobj, parameterType.IsPointer ? typeof(IntPtr) : parameterType); } } // Invoke the method. if (emitNew) { il.Emit(OpCodes.Newobj, (ConstructorInfo)method); } else if (method.IsStatic || method.DeclaringType !.IsValueType) { il.Emit(OpCodes.Call, (MethodInfo)method); }
internal static string ConstructName(MethodBase mi) { string str = null; str = str + mi.Name; RuntimeMethodInfo info = mi as RuntimeMethodInfo; if ((info != null) && info.IsGenericMethod) { str = str + info.m_handle.ConstructInstantiation(); } return (str + "(" + ConstructParameters(mi.GetParametersNoCopy(), mi.CallingConvention) + ")"); }
internal static string ConstructName(MethodBase mi) { string str = null; str = str + mi.Name; RuntimeMethodInfo info = mi as RuntimeMethodInfo; if ((info != null) && info.IsGenericMethod) { str = str + info.m_handle.ConstructInstantiation(); } return(str + "(" + ConstructParameters(mi.GetParametersNoCopy(), mi.CallingConvention) + ")"); }
private static int FindMostSpecificMethod(MethodBase m1, int[] paramOrder1, Type paramArrayType1, MethodBase m2, int[] paramOrder2, Type paramArrayType2, Type[] types, Object[] args) { // Find the most specific method based on the parameters. int res = FindMostSpecific(m1.GetParametersNoCopy(), paramOrder1, paramArrayType1, m2.GetParametersNoCopy(), paramOrder2, paramArrayType2, types, args); // If the match was not ambigous then return the result. if (res != 0) return res; // Check to see if the methods have the exact same name and signature. if (CompareMethodSigAndName(m1, m2)) { // Determine the depth of the declaring types for both methods. int hierarchyDepth1 = GetHierarchyDepth(m1.DeclaringType); int hierarchyDepth2 = GetHierarchyDepth(m2.DeclaringType); // The most derived method is the most specific one. if (hierarchyDepth1 == hierarchyDepth2) { return 0; } else if (hierarchyDepth1 < hierarchyDepth2) { return 2; } else { return 1; } } // The match is ambigous. return 0; }
internal static bool CompareMethodSigAndName(MethodBase m1, MethodBase m2) { ParameterInfo[] params1 = m1.GetParametersNoCopy(); ParameterInfo[] params2 = m2.GetParametersNoCopy(); if (params1.Length != params2.Length) return false; int numParams = params1.Length; for (int i = 0; i < numParams; i++) { if (params1[i].ParameterType != params2[i].ParameterType) return false; } return true; }
[System.Security.SecurityCritical] // auto-generated private int GetMemberRefToken(MethodBase methodInfo, Type[] optionalParameterTypes) { Type[] parameterTypes; if (optionalParameterTypes != null && (methodInfo.CallingConvention & CallingConventions.VarArgs) == 0) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention")); RuntimeMethodInfo rtMeth = methodInfo as RuntimeMethodInfo; DynamicMethod dm = methodInfo as DynamicMethod; if (rtMeth == null && dm == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), nameof(methodInfo)); ParameterInfo[] paramInfo = methodInfo.GetParametersNoCopy(); if (paramInfo != null && paramInfo.Length != 0) { parameterTypes = new Type[paramInfo.Length]; for (int i = 0; i < paramInfo.Length; i++) parameterTypes[i] = paramInfo[i].ParameterType; } else { parameterTypes = null; } SignatureHelper sig = GetMemberRefSignature(methodInfo.CallingConvention, MethodBuilder.GetMethodBaseReturnType(methodInfo), parameterTypes, optionalParameterTypes); if (rtMeth != null) return GetTokenForVarArgMethod(rtMeth, sig); else return GetTokenForVarArgMethod(dm, sig); }
/// <summary> /// 更新 params 参数信息,因为该参数类型中可能包含泛型类型参数。 /// </summary> /// <param name="newMethod">方法信息。</param> public void UpdateParamArrayType(MethodBase newMethod) { Contract.Requires(newMethod != null); if (this.paramArrayType != null) { ParameterInfo[] parameters = newMethod.GetParametersNoCopy(); this.paramArrayType = parameters[parameters.Length - 1].ParameterType; } }
/// <summary> /// 返回方法的参数信息。 /// </summary> /// <param name="method">要获取参数信息的方法。</param> /// <param name="types">方法实参类型数组,其长度必须大于等于方法的参数个数。 /// 使用 <see cref="Missing"/> 表示无需进行类型检查,<c>null</c> 表示引用类型标志。</param> /// <param name="options">方法参数信息的选项。</param> /// <returns>方法的参数信息。</returns> public static MethodArgumentsInfo GetInfo(MethodBase method, Type[] types, MethodArgumentsOption options) { Contract.Requires(method != null && types != null); MethodArgumentsInfo result = new MethodArgumentsInfo(method, types); bool optionalParamBinding = options.HasFlag(MethodArgumentsOption.OptionalParamBinding); bool isExplicit = options.HasFlag(MethodArgumentsOption.Explicit); bool convertRefType = options.HasFlag(MethodArgumentsOption.ConvertRefType); // 填充方法实例。 int offset = 0; if (options.HasFlag(MethodArgumentsOption.ContainsInstance)) { if (!result.MarkInstanceType(isExplicit, convertRefType)) { return null; } offset++; } // 填充 params 参数和可变参数。 if (!result.FillParamArray(isExplicit, convertRefType)) { return null; } // 检查实参是否与形参对应,未对应的参数是否包含默认值。 ParameterInfo[] parameters = method.GetParametersNoCopy(); int paramLen = parameters.Length; if (result.ParamArrayType != null) { paramLen--; Contract.Assume(paramLen >= 0); } for (int i = 0, j = offset; i < paramLen; i++, j++) { if (!CheckParameter(parameters[i], types[j], optionalParamBinding, isExplicit, convertRefType)) { return null; } } result.fixedArguments = new ArrayAdapter<Type>(types, offset, paramLen); return result; }
internal override int GetMemberRefToken(MethodBase methodInfo, Type[] optionalParameterTypes) { Type[] parameterTypes; if (optionalParameterTypes != null) if ((methodInfo.CallingConvention & CallingConventions.VarArgs) == 0) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention")); if (!(methodInfo is RuntimeMethodInfo) && DynamicMethod.AsDynamicMethod(methodInfo) == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "methodInfo"); ParameterInfo[] paramInfo = methodInfo.GetParametersNoCopy(); if (paramInfo != null && paramInfo.Length != 0) { parameterTypes = new Type[paramInfo.Length]; for (int i = 0; i < paramInfo.Length; i++) { parameterTypes[i] = paramInfo[i].ParameterType; } } else parameterTypes = null; SignatureHelper sig = GetMemberRefSignature(methodInfo.CallingConvention, methodInfo.GetReturnType(), parameterTypes, optionalParameterTypes); return m_scope.GetTokenFor(new VarArgMethod(methodInfo as MethodInfo, sig)); }
private static int FindMostSpecificMethod(MethodBase m1, int[] paramOrder1, Type paramArrayType1, MethodBase m2, int[] paramOrder2, Type paramArrayType2, Type[] types, object[] args) { int num = FindMostSpecific(m1.GetParametersNoCopy(), paramOrder1, paramArrayType1, m2.GetParametersNoCopy(), paramOrder2, paramArrayType2, types, args); if (num != 0) { return num; } if (!CompareMethodSigAndName(m1, m2)) { return 0; } int hierarchyDepth = GetHierarchyDepth(m1.DeclaringType); int num3 = GetHierarchyDepth(m2.DeclaringType); if (hierarchyDepth == num3) { return 0; } if (hierarchyDepth < num3) { return 2; } return 1; }
internal static bool CompareMethodSigAndName(MethodBase m1, MethodBase m2) { ParameterInfo[] parametersNoCopy = m1.GetParametersNoCopy(); ParameterInfo[] infoArray2 = m2.GetParametersNoCopy(); if (parametersNoCopy.Length != infoArray2.Length) { return false; } int length = parametersNoCopy.Length; for (int i = 0; i < length; i++) { if (parametersNoCopy[i].ParameterType != infoArray2[i].ParameterType) { return false; } } return true; }
public DynamicInvokeInfo(MethodBase method, IntPtr invokeThunk) { Method = method; InvokeThunk = invokeThunk; _isStatic = method.IsStatic; // _isValueTypeInstanceMethod = method.DeclaringType?.IsValueType ?? false; ParameterInfo[] parameters = method.GetParametersNoCopy(); _argumentCount = parameters.Length; if (_argumentCount != 0) { ArgumentInfo[] arguments = new ArgumentInfo[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Transform transform = default; Type argumentType = parameters[i].ParameterType; if (argumentType.IsByRef) { _needsCopyBack = true; transform |= Transform.ByRef; argumentType = argumentType.GetElementType() !; } Debug.Assert(!argumentType.IsByRef); EETypePtr eeArgumentType = argumentType.GetEEType(); if (eeArgumentType.IsValueType) { Debug.Assert(argumentType.IsValueType); if (eeArgumentType.IsByRefLike) { _argumentCount = ArgumentCount_NotSupported_ByRefLike; } if (eeArgumentType.IsNullable) { transform |= Transform.Nullable; } } else if (eeArgumentType.IsPointer) { Debug.Assert(argumentType.IsPointer); transform |= Transform.Pointer; } else { transform |= Transform.Reference; } arguments[i] = new ArgumentInfo(transform, eeArgumentType); } _arguments = arguments; } if (method is MethodInfo methodInfo) { Transform transform = default; Type returnType = methodInfo.ReturnType; if (returnType.IsByRef) { transform |= Transform.ByRef; returnType = returnType.GetElementType() !; } Debug.Assert(!returnType.IsByRef); EETypePtr eeReturnType = returnType.GetEEType(); if (eeReturnType.IsValueType) { Debug.Assert(returnType.IsValueType); if (returnType != typeof(void)) { if (eeReturnType.IsByRefLike) { _argumentCount = ArgumentCount_NotSupported_ByRefLike; } if ((transform & Transform.ByRef) == 0) { transform |= Transform.AllocateReturnBox; } if (eeReturnType.IsNullable) { transform |= Transform.Nullable; } } else { if ((transform & Transform.ByRef) != 0) { _argumentCount = ArgumentCount_NotSupported; // ByRef to void return } } } else if (eeReturnType.IsPointer) { Debug.Assert(returnType.IsPointer); transform |= Transform.Pointer; if ((transform & Transform.ByRef) == 0) { transform |= Transform.AllocateReturnBox; } } else { transform |= Transform.Reference; } _returnTransform = transform; _returnType = eeReturnType; } }
[System.Security.SecurityCritical] // auto-generated internal override int GetMemberRefToken(MethodBase methodInfo, Type[] optionalParameterTypes) { Type[] parameterTypes; if (optionalParameterTypes != null) { if ((methodInfo.CallingConvention & CallingConventions.VarArgs) == 0) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention")); } bool isValidMethod = (methodInfo is RuntimeMethodInfo) || (methodInfo is DynamicMethod); if (!isValidMethod) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "methodInfo"); // We want the creator of the DynamicMethod to control who has access to the // DynamicMethod (just like we do for delegates). However, a user can get to // the corresponding RTDynamicMethod using Exception.TargetSite, StackFrame.GetMethod, etc. // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would // not be able to bound access to the DynamicMethod. Hence, we do not allow // direct use of RTDynamicMethod. Contract.Assert(!(methodInfo is DynamicMethod.RTDynamicMethod), "Prevent direct use of RTDynamicMethod"); ParameterInfo[] paramInfo = methodInfo.GetParametersNoCopy(); if (paramInfo != null && paramInfo.Length != 0) { parameterTypes = new Type[paramInfo.Length]; for (int i = 0; i < paramInfo.Length; i++) { parameterTypes[i] = paramInfo[i].ParameterType; } } else { parameterTypes = null; } SignatureHelper sig = GetMemberRefSignature(methodInfo.CallingConvention, MethodBuilder.GetMethodBaseReturnType(methodInfo), parameterTypes, optionalParameterTypes); return m_scope.GetTokenFor(new VarArgMethod(methodInfo as RuntimeMethodInfo, methodInfo as DynamicMethod, sig)); }
internal static string ConstructName(MethodBase mi) { // Serialization uses ToString to resolve MethodInfo overloads. string toString = null; toString += mi.Name; RuntimeMethodInfo rmi = mi as RuntimeMethodInfo; if (rmi != null && rmi.IsGenericMethod) toString += rmi.m_handle.ConstructInstantiation(); toString += "(" + ConstructParameters(mi.GetParametersNoCopy(), mi.CallingConvention) + ")"; return toString; }
internal override int GetMemberRefToken(MethodBase methodInfo, Type[] optionalParameterTypes) { Type[] typeArray; if ((optionalParameterTypes != null) && ((methodInfo.CallingConvention & CallingConventions.VarArgs) == 0)) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention")); } if (!((methodInfo is RuntimeMethodInfo) || (methodInfo is DynamicMethod))) { throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "methodInfo"); } ParameterInfo[] parametersNoCopy = methodInfo.GetParametersNoCopy(); if ((parametersNoCopy != null) && (parametersNoCopy.Length != 0)) { typeArray = new Type[parametersNoCopy.Length]; for (int i = 0; i < parametersNoCopy.Length; i++) { typeArray[i] = parametersNoCopy[i].ParameterType; } } else { typeArray = null; } SignatureHelper signature = this.GetMemberRefSignature(methodInfo.CallingConvention, MethodBuilder.GetMethodBaseReturnType(methodInfo), typeArray, optionalParameterTypes); return this.m_scope.GetTokenFor(new VarArgMethod(methodInfo as RuntimeMethodInfo, methodInfo as DynamicMethod, signature)); }