private int GetMemberRefToken(MethodBase methodInfo, Type[]? optionalParameterTypes)
{
Type[]? parameterTypes;
+ Type[][]? requiredCustomModifiers;
+ Type[][]? optionalCustomModifiers;
if (optionalParameterTypes != null && (methodInfo.CallingConvention & CallingConventions.VarArgs) == 0)
throw new InvalidOperationException(SR.InvalidOperation_NotAVarArgCallingConvention);
if (paramInfo != null && paramInfo.Length != 0)
{
parameterTypes = new Type[paramInfo.Length];
+ requiredCustomModifiers = new Type[parameterTypes.Length][];
+ optionalCustomModifiers = new Type[parameterTypes.Length][];
+
for (int i = 0; i < paramInfo.Length; i++)
+ {
parameterTypes[i] = paramInfo[i].ParameterType;
+ requiredCustomModifiers[i] = paramInfo[i].GetRequiredCustomModifiers();
+ optionalCustomModifiers[i] = paramInfo[i].GetOptionalCustomModifiers();
+ }
}
else
{
parameterTypes = null;
+ requiredCustomModifiers = null;
+ optionalCustomModifiers = null;
}
SignatureHelper sig = GetMemberRefSignature(methodInfo.CallingConvention,
MethodBuilder.GetMethodBaseReturnType(methodInfo),
parameterTypes,
+ requiredCustomModifiers,
+ optionalCustomModifiers,
optionalParameterTypes);
if (rtMeth != null)
CallingConventions call,
Type? returnType,
Type[]? parameterTypes,
+ Type[][]? requiredCustomModifiers,
+ Type[][]? optionalCustomModifiers,
Type[]? optionalParameterTypes)
{
SignatureHelper sig = SignatureHelper.GetMethodSigHelper(call, returnType);
if (parameterTypes != null)
{
- foreach (Type t in parameterTypes)
- sig.AddArgument(t);
+ for (int i = 0; i < parameterTypes.Length; i++)
+ {
+ sig.AddArgument(parameterTypes[i], requiredCustomModifiers![i], optionalCustomModifiers![i]);
+ }
}
if (optionalParameterTypes != null && optionalParameterTypes.Length != 0)
{
return ((ModuleBuilder)m_methodBuilder.Module).GetMethodTokenInternal(method, optionalParameterTypes, useMethodDef);
}
+ internal SignatureHelper GetMemberRefSignature(
+ CallingConventions call,
+ Type? returnType,
+ Type[]? parameterTypes,
+ Type[]? optionalParameterTypes)
+ {
+ return GetMemberRefSignature(call, returnType, parameterTypes, null, null, optionalParameterTypes);
+ }
internal virtual SignatureHelper GetMemberRefSignature(CallingConventions call, Type? returnType,
- Type[]? parameterTypes, Type[]? optionalParameterTypes)
+ Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers, Type[]? optionalParameterTypes)
{
- return GetMemberRefSignature(call, returnType, parameterTypes, optionalParameterTypes, 0);
+ return GetMemberRefSignature(call, returnType, parameterTypes, requiredCustomModifiers, optionalCustomModifiers, optionalParameterTypes, 0);
}
private SignatureHelper GetMemberRefSignature(CallingConventions call, Type? returnType,
- Type[]? parameterTypes, Type[]? optionalParameterTypes, int cGenericParameters)
+ Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers, Type[]? optionalParameterTypes, int cGenericParameters)
{
- return ((ModuleBuilder)m_methodBuilder.Module).GetMemberRefSignature(call, returnType, parameterTypes, optionalParameterTypes, cGenericParameters);
+ return ((ModuleBuilder)m_methodBuilder.Module).GetMemberRefSignature(call, returnType, parameterTypes, requiredCustomModifiers, optionalCustomModifiers, optionalParameterTypes, cGenericParameters);
}
internal byte[]? BakeByteArray()
return (m as RuntimeModule)!;
}
- private int GetMemberRefToken(MethodBase method, IEnumerable<Type>? optionalParameterTypes)
+ private int GetMemberRefToken(MethodBase method, Type[]? optionalParameterTypes)
{
- Type[] parameterTypes;
- Type? returnType;
int tkParent;
int cGenericParameters = 0;
+ SignatureHelper sigHelp;
if (method.IsGenericMethod)
{
if (method.DeclaringType!.IsGenericType)
{
- MethodBase methDef; // methodInfo = G<Foo>.M<Bar> ==> methDef = G<T>.M<S>
+ MethodBase methDef = GetGenericMethodBaseDefinition(method);
- if (method is MethodOnTypeBuilderInstantiation motbi)
- {
- methDef = motbi.m_method;
- }
- else if (method is ConstructorOnTypeBuilderInstantiation cotbi)
- {
- methDef = cotbi.m_ctor;
- }
- else if (method is MethodBuilder || method is ConstructorBuilder)
- {
- // methodInfo must be GenericMethodDefinition; trying to emit G<?>.M<S>
- methDef = method;
- }
- else
- {
- Debug.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
-
- if (method.IsGenericMethod)
- {
- Debug.Assert(masmi != null);
-
- methDef = masmi.GetGenericMethodDefinition()!;
- methDef = methDef.Module.ResolveMethod(
- method.MetadataToken,
- methDef.DeclaringType?.GetGenericArguments(),
- methDef.GetGenericArguments())!;
- }
- else
- {
- methDef = method.Module.ResolveMethod(
- method.MetadataToken,
- method.DeclaringType?.GetGenericArguments(),
- null)!;
- }
- }
-
- parameterTypes = methDef.GetParameterTypes();
- returnType = MethodBuilder.GetMethodBaseReturnType(methDef);
+ sigHelp = GetMemberRefSignature(methDef, cGenericParameters);
}
else
{
- parameterTypes = method.GetParameterTypes();
- returnType = MethodBuilder.GetMethodBaseReturnType(method);
+ sigHelp = GetMemberRefSignature(method, cGenericParameters);
}
- byte[] sigBytes = GetMemberRefSignature(method.CallingConvention, returnType, parameterTypes,
- optionalParameterTypes, cGenericParameters).InternalGetSignature(out int sigLength);
+ if (optionalParameterTypes?.Length > 0)
+ {
+ sigHelp.AddSentinel();
+ sigHelp.AddArguments(optionalParameterTypes, null, null);
+ }
+
+ byte[] sigBytes = sigHelp.InternalGetSignature(out int sigLength);
if (method.DeclaringType!.IsGenericType)
{
}
internal SignatureHelper GetMemberRefSignature(CallingConventions call, Type? returnType,
- Type[]? parameterTypes, IEnumerable<Type>? optionalParameterTypes, int cGenericParameters)
+ Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers,
+ IEnumerable<Type>? optionalParameterTypes, int cGenericParameters)
{
SignatureHelper sig = SignatureHelper.GetMethodSigHelper(this, call, returnType, cGenericParameters);
if (parameterTypes != null)
{
- foreach (Type t in parameterTypes)
+ for (int i = 0; i < parameterTypes.Length; i++)
{
- sig.AddArgument(t);
+ sig.AddArgument(parameterTypes[i], requiredCustomModifiers![i], optionalCustomModifiers![i]);
}
}
return sig;
}
+ private MethodBase GetGenericMethodBaseDefinition(MethodBase methodBase)
+ {
+ // methodInfo = G<Foo>.M<Bar> ==> methDef = G<T>.M<S>
+ MethodInfo? masmi = methodBase as MethodInfo;
+ MethodBase methDef;
+
+ if (methodBase is MethodOnTypeBuilderInstantiation motbi)
+ {
+ methDef = motbi.m_method;
+ }
+ else if (methodBase is ConstructorOnTypeBuilderInstantiation cotbi)
+ {
+ methDef = cotbi.m_ctor;
+ }
+ else if (methodBase is MethodBuilder || methodBase is ConstructorBuilder)
+ {
+ // methodInfo must be GenericMethodDefinition; trying to emit G<?>.M<S>
+ methDef = methodBase;
+ }
+ else
+ {
+ Debug.Assert(methodBase is RuntimeMethodInfo || methodBase is RuntimeConstructorInfo);
+
+ if (methodBase.IsGenericMethod)
+ {
+ Debug.Assert(masmi != null);
+
+ methDef = masmi.GetGenericMethodDefinition()!;
+ methDef = methDef.Module.ResolveMethod(
+ methodBase.MetadataToken,
+ methDef.DeclaringType?.GetGenericArguments(),
+ methDef.GetGenericArguments())!;
+ }
+ else
+ {
+ methDef = methodBase.Module.ResolveMethod(
+ methodBase.MetadataToken,
+ methodBase.DeclaringType?.GetGenericArguments(),
+ null)!;
+ }
+ }
+
+ return methDef;
+ }
+
+ internal SignatureHelper GetMemberRefSignature(MethodBase? method, int cGenericParameters)
+ {
+ switch (method)
+ {
+ case MethodBuilder methodBuilder:
+ return methodBuilder.GetMethodSignature();
+ case ConstructorBuilder constructorBuilder:
+ return constructorBuilder.GetMethodSignature();
+ case MethodOnTypeBuilderInstantiation motbi when motbi.m_method is MethodBuilder methodBuilder:
+ return methodBuilder.GetMethodSignature();
+ case MethodOnTypeBuilderInstantiation motbi:
+ method = motbi.m_method;
+ break;
+ case ConstructorOnTypeBuilderInstantiation cotbi when cotbi.m_ctor is ConstructorBuilder constructorBuilder:
+ return constructorBuilder.GetMethodSignature();
+ case ConstructorOnTypeBuilderInstantiation cotbi:
+ method = cotbi.m_ctor;
+ break;
+ }
+
+ Debug.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
+ ParameterInfo[] parameters = method.GetParametersNoCopy();
+
+ Type[] parameterTypes = new Type[parameters.Length];
+ Type[][] requiredCustomModifiers = new Type[parameterTypes.Length][];
+ Type[][] optionalCustomModifiers = new Type[parameterTypes.Length][];
+
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameterTypes[i] = parameters[i].ParameterType;
+ requiredCustomModifiers[i] = parameters[i].GetRequiredCustomModifiers();
+ optionalCustomModifiers[i] = parameters[i].GetOptionalCustomModifiers();
+ }
+
+ ParameterInfo? returnParameter = method is MethodInfo mi ? mi.ReturnParameter : null;
+ SignatureHelper sigHelp = SignatureHelper.GetMethodSigHelper(this, method.CallingConvention, cGenericParameters, returnParameter?.ParameterType, returnParameter?.GetRequiredCustomModifiers(), returnParameter?.GetOptionalCustomModifiers(), parameterTypes, requiredCustomModifiers, optionalCustomModifiers);
+ return sigHelp;
+ }
+
#endregion
public override bool Equals(object? obj) => InternalModule.Equals(obj);
return new MethodToken(mr);
}
- internal int GetMethodTokenInternal(MethodBase method, IEnumerable<Type>? optionalParameterTypes, bool useMethodDef)
+ internal int GetMethodTokenInternal(MethodBase method, Type[]? optionalParameterTypes, bool useMethodDef)
{
int tk;
MethodInfo? methodInfo = method as MethodInfo;
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Reflection.Emit.Tests
+{
+ public interface IWithIn<T>
+ {
+ void Method(in int arg);
+ }
+ public class ILGeneratorEmitMethodInfo
+ {
+ [Fact]
+ public void EmitMethodInfo()
+ {
+ Type methodType = typeof(IWithIn<int>);
+ MethodInfo method = methodType.GetMethod("Method");
+ MethodInfo getMethodFromHandle = typeof(MethodBase).GetMethod("GetMethodFromHandle", new[] { typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle) });
+
+ ModuleBuilder moduleBuilder = Helpers.DynamicModule();
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("DynamicType", TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Class);
+
+ MethodBuilder methodBuilder = typeBuilder.DefineMethod("Get", MethodAttributes.Public | MethodAttributes.Static, typeof(MethodBase), new Type[0]);
+ ILGenerator ilBuilder = methodBuilder.GetILGenerator();
+ ilBuilder.Emit(OpCodes.Ldtoken, method);
+ ilBuilder.Emit(OpCodes.Ldtoken, methodType);
+ ilBuilder.Emit(OpCodes.Call, getMethodFromHandle);
+ ilBuilder.Emit(OpCodes.Ret);
+
+ Type type = typeBuilder.CreateType();
+
+ MethodInfo genMethod = type.GetMethod("Get");
+ byte[] il = genMethod.GetMethodBody().GetILAsByteArray();
+
+ int ilMethodMetadataToken = BitConverter.ToInt32(il, 1);
+ MethodBase resolvedMethod = type.Module.ResolveMethod(ilMethodMetadataToken);
+ Assert.Equal(method, resolvedMethod);
+ var methodBase = (MethodBase)genMethod.Invoke(null, null);
+ Assert.Equal(method, methodBase);
+ }
+ }
+}