Files

779 lines
31 KiB
C#

// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
// Source: http://stackoverflow.com/questions/4968755/mono-cecil-call-generic-base-class-method-from-other-assembly
using System.Reflection;
using System.Text;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using Stride.Core.Storage;
namespace Stride.Core.AssemblyProcessor;
public static class CecilExtensions
{
// Not sure why Cecil made ContainsGenericParameter internal, but let's work around it by reflection.
private static readonly MethodInfo containsGenericParameterGetMethod = typeof(MemberReference).GetProperty("ContainsGenericParameter", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetMethod;
public static bool IsResolvedValueType(this TypeReference type)
{
if (type.GetType() == typeof(TypeReference))
type = type.Resolve();
return type.IsValueType;
}
public static MethodDefinition GetEmptyConstructor(this TypeDefinition type, bool allowPrivate = false)
{
return type.Methods.FirstOrDefault(x => x.IsConstructor && (x.IsPublic || allowPrivate) && !x.IsStatic && x.Parameters.Count == 0);
}
public static ModuleDefinition GetStrideCoreModule(this AssemblyDefinition assembly)
{
var strideCoreAssembly = assembly.Name.Name == "Stride.Core"
? assembly
: assembly.MainModule.AssemblyResolver.Resolve(new AssemblyNameReference("Stride.Core", null));
return strideCoreAssembly.MainModule;
}
public static TypeReference MakeGenericType(this TypeReference self, params TypeReference[] arguments)
{
if (self.GenericParameters.Count != arguments.Length)
throw new ArgumentException();
if (arguments.Length == 0)
return self;
var instance = new GenericInstanceType(self);
foreach (var argument in arguments)
instance.GenericArguments.Add(argument);
return instance;
}
public static FieldReference MakeGeneric(this FieldReference self, params TypeReference[] arguments)
{
if (arguments.Length == 0)
return self;
return new FieldReference(self.Name, self.FieldType, self.DeclaringType.MakeGenericType(arguments));
}
public static MethodReference MakeGeneric(this MethodReference self, params TypeReference[] arguments)
{
if (arguments.Length == 0)
return self;
var reference = new MethodReference(self.Name, self.ReturnType, self.DeclaringType.MakeGenericType(arguments))
{
HasThis = self.HasThis,
ExplicitThis = self.ExplicitThis,
CallingConvention = self.CallingConvention,
};
foreach (var parameter in self.Parameters)
reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
CopyGenericParameters(self, reference);
return reference;
}
private static void CopyGenericParameters(MethodReference self, MethodReference reference)
{
foreach (var genericParameter in self.GenericParameters)
{
var genericParameterCopy = new GenericParameter(genericParameter.Name, reference)
{
Attributes = genericParameter.Attributes,
};
reference.GenericParameters.Add(genericParameterCopy);
foreach (var constraint in genericParameter.Constraints)
genericParameterCopy.Constraints.Add(constraint);
}
}
public static MethodReference MakeGenericMethod(this MethodReference self, params TypeReference[] arguments)
{
if (self.GenericParameters.Count != arguments.Length)
throw new ArgumentException();
var method = new GenericInstanceMethod(self);
foreach(var argument in arguments)
method.GenericArguments.Add(argument);
return method;
}
public static MethodDefinition OpenModuleConstructor(this AssemblyDefinition assembly, out Instruction returnInstruction)
{
// Get or create module static constructor
var voidType = assembly.MainModule.TypeSystem.Void;
var moduleClass = assembly.MainModule.Types.First(t => t.Name == "<Module>");
var staticConstructor = moduleClass.GetStaticConstructor();
if (staticConstructor == null)
{
staticConstructor = new MethodDefinition(".cctor",
Mono.Cecil.MethodAttributes.Private | Mono.Cecil.MethodAttributes.HideBySig | Mono.Cecil.MethodAttributes.Static | Mono.Cecil.MethodAttributes.SpecialName | Mono.Cecil.MethodAttributes.RTSpecialName,
voidType);
staticConstructor.Body.GetILProcessor().Append(Instruction.Create(OpCodes.Ret));
moduleClass.Methods.Add(staticConstructor);
}
returnInstruction = staticConstructor.Body.Instructions.Last();
return staticConstructor;
}
public static TypeDefinition GetTypeResolved(this ModuleDefinition moduleDefinition, string typeName)
{
foreach (var exportedType in moduleDefinition.ExportedTypes)
{
if (exportedType.FullName == typeName)
{
var typeDefinition = exportedType.Resolve();
return typeDefinition;
}
}
return moduleDefinition.GetType(typeName);
}
public static TypeDefinition GetTypeResolved(this ModuleDefinition moduleDefinition, string @namespace, string typeName)
{
foreach (var exportedType in moduleDefinition.ExportedTypes)
{
if (exportedType.Namespace == @namespace && exportedType.Name == typeName)
{
return exportedType.Resolve();
}
}
return moduleDefinition.GetType(@namespace, typeName);
}
/// <summary>
/// Finds the corlib assembly which can be either mscorlib.dll or System.Runtime.dll depending on the .NET runtime environment.
/// </summary>
/// <param name="assembly">Assembly where System.Object is found.</param>
/// <returns></returns>
public static AssemblyDefinition FindCorlibAssembly(AssemblyDefinition assembly)
{
// Ask Cecil for the core library which will be either mscorlib or System.Runtime.
AssemblyNameReference corlibReference = assembly.MainModule.TypeSystem.CoreLibrary as AssemblyNameReference;
return assembly.MainModule.AssemblyResolver.Resolve(corlibReference);
}
/// <summary>
/// Finds the assembly in which the generic collections are defined. This can be either in mscorlib.dll or in System.Collections.dll depending on the .NET runtime environment.
/// </summary>
/// <param name="assembly">Assembly where the generic collections are defined.</param>
/// <returns></returns>
public static AssemblyDefinition FindCollectionsAssembly(AssemblyDefinition assembly)
{
// Ask Cecil for the core library which will be either mscorlib or System.Runtime.
var corlibReference = FindCorlibAssembly(assembly);
if (string.Equals(corlibReference.Name.Name, "system.runtime", StringComparison.OrdinalIgnoreCase))
{
// The core library is System.Runtime, so the collections assemblies are in System.Collections.dll.
// First we look if it is not already referenced by `assembly' and if not, we made an explicit reference
// to System.Collections.
var collectionsAssembly = assembly.MainModule.AssemblyReferences.FirstOrDefault(ass => string.Equals(ass.Name, "system.collections", StringComparison.OrdinalIgnoreCase));
collectionsAssembly ??= new AssemblyNameReference("System.Collections", new Version(4,0,0,0));
return assembly.MainModule.AssemblyResolver.Resolve(collectionsAssembly);
}
else
{
return corlibReference;
}
}
/// <summary>
/// Finds the assembly in which the generic collections are defined. This can be either in mscorlib.dll or in System.Collections.dll depending on the .NET runtime environment.
/// </summary>
/// <param name="assembly">Assembly where the generic collections are defined.</param>
/// <returns></returns>
public static AssemblyDefinition FindReflectionAssembly(AssemblyDefinition assembly)
{
// Ask Cecil for the core library which will be either mscorlib or System.Runtime.
var corlibReference = FindCorlibAssembly(assembly);
if (string.Equals(corlibReference.Name.Name, "system.runtime", StringComparison.OrdinalIgnoreCase))
{
// The core library is System.Runtime, so the collections assemblies are in System.Collections.dll.
// First we look if it is not already referenced by `assembly' and if not, we made an explicit reference
// to System.Collections.
var collectionsAssembly = assembly.MainModule.AssemblyReferences.FirstOrDefault(ass => string.Equals(ass.Name, "system.reflection", StringComparison.OrdinalIgnoreCase));
collectionsAssembly ??= new AssemblyNameReference("System.Reflection", new Version(4, 0, 0, 0));
return assembly.MainModule.AssemblyResolver.Resolve(collectionsAssembly);
}
else
{
return corlibReference;
}
}
/// <summary>
/// Get AssemblyProcessorProgram Files x86
/// </summary>
/// <returns></returns>
public static string ProgramFilesx86()
{
if (8 == IntPtr.Size
|| (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"))))
{
return Environment.GetEnvironmentVariable("ProgramFiles(x86)");
}
return Environment.GetEnvironmentVariable("ProgramFiles");
}
public static GenericInstanceType ChangeGenericInstanceType(this GenericInstanceType type, TypeReference elementType, IEnumerable<TypeReference> genericArguments)
{
if (elementType != type.ElementType || genericArguments != type.GenericArguments)
{
var result = new GenericInstanceType(elementType);
foreach (var genericArgument in genericArguments)
result.GenericArguments.Add(genericArgument);
if (type.HasGenericParameters)
SetGenericParameters(result, type.GenericParameters);
return result;
}
return type;
}
public static ArrayType ChangeArrayType(this ArrayType type, TypeReference elementType, int rank)
{
if (elementType != type.ElementType || rank != type.Rank)
{
var result = new ArrayType(elementType, rank);
if (type.HasGenericParameters)
SetGenericParameters(result, type.GenericParameters);
return result;
}
return type;
}
public static PointerType ChangePointerType(this PointerType type, TypeReference elementType)
{
if (elementType != type.ElementType)
{
var result = new PointerType(elementType);
if (type.HasGenericParameters)
SetGenericParameters(result, type.GenericParameters);
return result;
}
return type;
}
public static PinnedType ChangePinnedType(this PinnedType type, TypeReference elementType)
{
if (elementType != type.ElementType)
{
var result = new PinnedType(elementType);
if (type.HasGenericParameters)
SetGenericParameters(result, type.GenericParameters);
return result;
}
return type;
}
public static TypeReference ChangeGenericParameters(this TypeReference type, IEnumerable<GenericParameter> genericParameters)
{
if (type.GenericParameters == genericParameters)
return type;
TypeReference result;
if (type is ArrayType arrayType)
{
result = new ArrayType(arrayType.ElementType, arrayType.Rank);
}
else
{
if (type is GenericInstanceType genericInstanceType)
{
result = new GenericInstanceType(genericInstanceType.ElementType);
}
else if (type.GetType() == typeof(TypeReference).GetType())
{
result = new TypeReference(type.Namespace, type.Name, type.Module, type.Scope, type.IsValueType);
}
else
{
throw new NotSupportedException();
}
}
SetGenericParameters(result, genericParameters);
return result;
}
/// <summary>
/// Sometimes, TypeReference.IsValueType is not properly set (since it needs to load dependent assembly).
/// THis do so when necessary.
/// </summary>
/// <param name="typeReference"></param>
/// <returns></returns>
public static TypeReference FixupValueType(this TypeReference typeReference)
{
return FixupValueTypeVisitor.Default.VisitDynamic(typeReference);
}
private static void SetGenericParameters(TypeReference result, IEnumerable<GenericParameter> genericParameters)
{
foreach (var genericParameter in genericParameters)
result.GenericParameters.Add(genericParameter);
}
public static string GenerateGenerics(this TypeReference type, bool empty = false)
{
var genericInstanceType = type as GenericInstanceType;
if (!type.HasGenericParameters && genericInstanceType == null)
return string.Empty;
var result = new StringBuilder();
// Try to process generic instantiations
if (genericInstanceType != null)
{
result.Append("<");
bool first = true;
foreach (var genericArgument in genericInstanceType.GenericArguments)
{
if (!first)
result.Append(",");
first = false;
if (!empty)
result.Append(ConvertCSharp(genericArgument, empty));
}
result.Append(">");
return result.ToString();
}
if (type.HasGenericParameters)
{
result.Append("<");
bool first = true;
foreach (var genericParameter in type.GenericParameters)
{
if (!first)
result.Append(",");
first = false;
if (!empty)
result.Append(ConvertCSharp(genericParameter, empty));
}
result.Append(">");
return result.ToString();
}
return result.ToString();
}
public static unsafe string ConvertTypeId(this TypeReference type)
{
var typeName = type.ConvertCSharp(false);
var typeId = ObjectId.FromBytes(Encoding.UTF8.GetBytes(typeName));
var typeIdHash = (uint*)&typeId;
return string.Format("new {0}(0x{1:x8}, 0x{2:x8}, 0x{3:x8}, 0x{4:x8})", typeof(ObjectId).FullName, typeIdHash[0], typeIdHash[1], typeIdHash[2], typeIdHash[3]);
}
/// <summary>
/// Generates type name valid to use from C# source file.
/// </summary>
/// <param name="type"></param>
/// <param name="empty"></param>
/// <returns></returns>
public static string ConvertCSharp(this TypeReference type, bool empty = false)
{
// Try to process arrays
if (type is ArrayType arrayType)
{
return ConvertCSharp(arrayType.ElementType, empty) + "[]";
}
// Remove the `X at end of generic definition.
var typeName = type.GetElementType().FullName;
var genericSeparatorIndex = typeName.LastIndexOf('`');
if (genericSeparatorIndex != -1)
typeName = typeName[..genericSeparatorIndex];
// Replace / into . (nested types)
typeName = typeName.Replace('/', '.');
// Try to process generic instantiations
if (type is GenericInstanceType genericInstanceType)
{
var result = new StringBuilder();
// Use ElementType so that we have only the name without the <> part.
result.Append(typeName);
result.Append("<");
bool first = true;
foreach (var genericArgument in genericInstanceType.GenericArguments)
{
if (!first)
result.Append(",");
first = false;
if (!empty)
result.Append(ConvertCSharp(genericArgument, empty));
}
result.Append(">");
return result.ToString();
}
if (type.HasGenericParameters)
{
var result = new StringBuilder();
// Use ElementType so that we have only the name without the <> part.
result.Append(typeName);
result.Append("<");
bool first = true;
foreach (var genericParameter in type.GenericParameters)
{
if (!first)
result.Append(",");
first = false;
if (!empty)
result.Append(ConvertCSharp(genericParameter, empty));
}
result.Append(">");
return result.ToString();
}
return typeName;
}
/// <summary>
/// Generates the Mono.Cecil TypeReference from its .NET <see cref="Type"/> counterpart.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="assemblyResolver">The assembly resolver.</param>
/// <returns></returns>
public static TypeReference GenerateTypeCecil(this Type type, BaseAssemblyResolver assemblyResolver)
{
var assemblyDefinition = assemblyResolver.Resolve(AssemblyNameReference.Parse(type.Assembly.FullName));
TypeReference typeReference;
if (type.IsNested)
{
var declaringType = GenerateTypeCecil(type.DeclaringType, assemblyResolver);
typeReference = declaringType.Resolve().NestedTypes.FirstOrDefault(x => x.Name == type.Name);
}
else if (type.IsArray)
{
var elementType = GenerateTypeCecil(type.GetElementType(), assemblyResolver);
typeReference = new ArrayType(elementType, type.GetArrayRank());
}
else
{
typeReference = assemblyDefinition.MainModule.GetTypeResolved(type.IsGenericType ? type.GetGenericTypeDefinition().FullName : type.FullName);
}
if (typeReference == null)
throw new InvalidOperationException("Could not resolve cecil type.");
if (type.IsGenericType)
{
var genericInstanceType = new GenericInstanceType(typeReference);
foreach (var argType in type.GetGenericArguments())
{
TypeReference argTypeReference;
if (argType.IsGenericParameter)
{
argTypeReference = new GenericParameter(argType.Name, typeReference);
}
else
{
argTypeReference = GenerateTypeCecil(argType, assemblyResolver);
}
genericInstanceType.GenericArguments.Add(argTypeReference);
}
typeReference = genericInstanceType;
}
return typeReference;
}
public static bool ContainsGenericParameter(this MemberReference memberReference)
{
return (bool)containsGenericParameterGetMethod.Invoke(memberReference, null);
}
/// <summary>
/// Generates type name similar to Type.AssemblyQualifiedName.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static string ConvertAssemblyQualifiedName(this TypeReference type)
{
var result = new StringBuilder(256);
ConvertAssemblyQualifiedName(type, result);
return result.ToString();
}
private static void ConvertAssemblyQualifiedName(this TypeReference type, StringBuilder result)
{
int start, end;
var arrayType = type as ArrayType;
if (arrayType != null)
{
// If it's an array, process element type, and add [] after
type = arrayType.ElementType;
}
// Add FUllName from GetElementType() (remove generics etc...)
start = result.Length;
result.Append(type.GetElementType().FullName);
end = result.Length;
// Replace / into + (nested types)
result = result.Replace('/', '+', start, end);
// Try to process generic instantiations
if (type is GenericInstanceType genericInstanceType)
{
// Ideally we would like to have access to Mono.Cecil TypeReference.ContainsGenericParameter, but it's internal.
// This doesn't cover every case but hopefully this should be enough for serialization
bool containsGenericParameter = false;
foreach (var genericArgument in genericInstanceType.GenericArguments)
{
if (genericArgument.IsGenericParameter)
containsGenericParameter = true;
}
if (!containsGenericParameter)
{
// Use ElementType so that we have only the name without the <> part.
result.Append('[');
bool first = true;
foreach (var genericArgument in genericInstanceType.GenericArguments)
{
if (!first)
result.Append(",");
result.Append('[');
first = false;
result.Append(ConvertAssemblyQualifiedName(genericArgument));
result.Append(']');
}
result.Append(']');
}
}
// Try to process arrays
if (arrayType != null)
{
result.Append('[');
if (arrayType.Rank > 1)
result.Append(',', arrayType.Rank - 1);
result.Append(']');
}
result.Append(", ");
start = result.Length;
result.Append(type.Module.Assembly.FullName);
end = result.Length;
#if STRIDE_PLATFORM_MONO_MOBILE
// Xamarin iOS and Android remap some assemblies
const string oldTypeEnding = "2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e";
const string newTypeEnding = "4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
result = result.Replace(oldTypeEnding, newTypeEnding, start, end);
#endif
}
public static void AddRange<T>(this ICollection<T> list, IEnumerable<T> items)
{
if (list is List<T> l)
{
l.AddRange(items);
}
else
{
foreach (var item in items)
{
list.Add(item);
}
}
}
public static void InflateGenericType(TypeDefinition genericType, TypeDefinition inflatedType, params TypeReference[] genericTypes)
{
// Base type
var genericMapping = new Dictionary<TypeReference, TypeReference>();
for (int i = 0; i < genericTypes.Length; ++i)
{
genericMapping.Add(genericType.GenericParameters[i], genericTypes[i]);
}
var resolveGenericsVisitor = new ResolveGenericsVisitor(genericMapping);
inflatedType.BaseType = inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(genericType.BaseType));
// Some stuff are not handled yet
if (genericType.HasNestedTypes)
{
throw new NotImplementedException();
}
foreach (var field in genericType.Fields)
{
var clonedField = new FieldDefinition(field.Name, field.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(field.FieldType)));
inflatedType.Fields.Add(clonedField);
}
foreach (var property in genericType.Properties)
{
if (property.HasParameters)
throw new NotImplementedException();
var clonedProperty = new PropertyDefinition(property.Name, property.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(property.PropertyType)))
{
HasThis = property.HasThis,
GetMethod = property.GetMethod != null ? InflateMethod(inflatedType, property.GetMethod, resolveGenericsVisitor) : null,
SetMethod = property.SetMethod != null ? InflateMethod(inflatedType, property.SetMethod, resolveGenericsVisitor) : null,
};
inflatedType.Properties.Add(clonedProperty);
}
// Clone methods
foreach (var method in genericType.Methods)
{
var clonedMethod = InflateMethod(inflatedType, method, resolveGenericsVisitor);
inflatedType.Methods.Add(clonedMethod);
}
}
private static MethodDefinition InflateMethod(TypeDefinition inflatedType, MethodDefinition method, ResolveGenericsVisitor resolveGenericsVisitor)
{
var clonedMethod = new MethodDefinition(method.Name, method.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(method.ReturnType)));
clonedMethod.Parameters.AddRange(
method.Parameters.Select(x => new ParameterDefinition(x.Name, x.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(x.ParameterType)))));
if (method.Body != null)
{
clonedMethod.Body.Variables.AddRange(
method.Body.Variables.Select(x => new VariableDefinition(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(x.VariableType)))));
clonedMethod.Body.InitLocals = method.Body.InitLocals;
var mappedInstructions = new Dictionary<Instruction, Instruction>();
foreach (var instruction in method.Body.Instructions)
{
// Create nop instructions to start with (if we use actual opcode, it would do an operand check)
var mappedInstruction = Instruction.Create(OpCodes.Nop);
mappedInstruction.OpCode = instruction.OpCode;
mappedInstruction.Operand = instruction.Operand;
mappedInstructions[instruction] = mappedInstruction;
}
foreach (var instruction in method.Body.Instructions)
{
// Fix operand
var mappedInstruction = mappedInstructions[instruction];
if (mappedInstruction.Operand is Instruction)
{
mappedInstruction.Operand = mappedInstructions[(Instruction)instruction.Operand];
}
else if (mappedInstruction.Operand is ParameterDefinition)
{
var parameterIndex = method.Parameters.IndexOf((ParameterDefinition)instruction.Operand);
mappedInstruction.Operand = clonedMethod.Parameters[parameterIndex];
}
else if (mappedInstruction.Operand is VariableDefinition)
{
var variableIndex = method.Body.Variables.IndexOf((VariableDefinition)instruction.Operand);
mappedInstruction.Operand = clonedMethod.Body.Variables[variableIndex];
}
else if (mappedInstruction.Operand is TypeReference reference)
{
var newTypeReference = resolveGenericsVisitor.VisitDynamic(reference);
newTypeReference = inflatedType.Module.ImportReference(newTypeReference);
mappedInstruction.Operand = newTypeReference;
}
else if (mappedInstruction.Operand is FieldReference fieldReference)
{
var newFieldReference = new FieldReference(fieldReference.Name,
inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(fieldReference.FieldType)),
inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(fieldReference.DeclaringType)));
mappedInstruction.Operand = newFieldReference;
}
else if (mappedInstruction.Operand is MethodReference methodReference)
{
var genericInstanceMethod = methodReference as GenericInstanceMethod;
if (genericInstanceMethod != null)
{
methodReference = genericInstanceMethod.ElementMethod;
}
methodReference = methodReference.GetElementMethod();
var newMethodReference = new MethodReference(methodReference.Name,
inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(methodReference.ReturnType)),
inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(methodReference.DeclaringType)))
{
HasThis = methodReference.HasThis,
ExplicitThis = methodReference.ExplicitThis,
CallingConvention = methodReference.CallingConvention,
};
foreach (var parameter in methodReference.Parameters)
newMethodReference.Parameters.Add(new ParameterDefinition(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(parameter.ParameterType))));
if (methodReference.HasGenericParameters)
{
CopyGenericParameters(methodReference, newMethodReference);
}
if (genericInstanceMethod != null)
{
newMethodReference = newMethodReference.MakeGenericMethod(genericInstanceMethod.GenericArguments.Select(x => inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(x))).ToArray());
}
mappedInstruction.Operand = newMethodReference;
}
else if (mappedInstruction.Operand is CallSite callSite)
{
var newCallSite = new CallSite(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(callSite.ReturnType)))
{
HasThis = callSite.HasThis,
ExplicitThis = callSite.ExplicitThis,
CallingConvention = callSite.CallingConvention,
};
foreach (var parameter in callSite.Parameters)
newCallSite.Parameters.Add(new ParameterDefinition(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(parameter.ParameterType))));
mappedInstruction.Operand = newCallSite;
}
else if (mappedInstruction.Operand is Instruction[])
{
// Not used in UpdatableProperty<T>
throw new NotImplementedException();
}
}
clonedMethod.Body.Instructions.AddRange(method.Body.Instructions.Select(x => mappedInstructions[x]));
}
return clonedMethod;
}
}