private void InjectSpecializationsInMethod(MethodDefinition method, List <SpecializationInfo> specializations) { foreach (var local in method.Body.Variables) { local.VariableType = FindSpecializedType(local.VariableType, specializations); } foreach (var instruction in method.Body.Instructions) { switch (instruction.Operand) { case TypeReference typeref: instruction.Operand = FindSpecializedType(typeref, specializations); break; case MethodReference methodref: if (!(methodref.DeclaringType is GenericInstanceType genericInstanceType)) { break; } var specializationArg = genericInstanceType.GenericArguments[0]; var newref = _moduleDefinition.ImportReference( specializations.Select(x => x.SpecializedMethods.FirstOrDefault(y => y.Key.Resolve() == methodref.Resolve() && MetadataComparer.AreSame(specializationArg, x.Specialization)) is var pair && pair.Value != null ? InsertRemainingGenerics(pair.Value, genericInstanceType) : null) .FirstOrDefault(x => x != null) ?? methodref); if (methodref is GenericInstanceMethod genericInstanceMethod && newref != methodref) { newref = newref.MakeGenericInstanceMethod( genericInstanceMethod.GenericArguments .Select(x => FindSpecializedType(x, specializations)).ToArray()); } instruction.Operand = newref; break; } } }
private TypeReference FindSpecializedType(TypeReference type, List <SpecializationInfo> specializations) { if (!(type is GenericInstanceType genericInstanceType) || genericInstanceType.GenericArguments.Count != 1) { return(type); } var decl = type.Resolve(); if (specializations.SingleOrDefault(x => x.GenericClass == decl && MetadataComparer.AreSame(x.Specialization, genericInstanceType.GenericArguments[0])) is SpecializationInfo specialization) { return(specialization.SpecializedClass); } else { return(type); } }