private MethodDefinition ExposeMethod(TypeDefinition typeToProcess, FieldReference fieldToProcess, MethodReference methodToExpose, ExposeMode exposeMode, MethodSemanticsAttributes semanticAttributes) { var typeToExpose = fieldToProcess.FieldType; var genericTypeToExpose = typeToExpose as GenericInstanceType; MethodReference methodToExposeWithResolvedGenerics = null; if (genericTypeToExpose != null) { methodToExposeWithResolvedGenerics = methodToExpose.With(declaringType: methodToExpose.DeclaringType.MakeGenericInstanceType(genericTypeToExpose.GenericArguments.ToArray()), resolveGenericReturnTypeAndParameterTypes: true); methodToExpose = methodToExpose.With(declaringType: methodToExpose.DeclaringType.MakeGenericInstanceType(genericTypeToExpose.GenericArguments.ToArray()), resolveGenericReturnTypeAndParameterTypes: false); } var name = exposeMode == ExposeMode.ImplementExplicit ? typeToExpose.FullName + "." + methodToExpose.Name : methodToExpose.Name; MethodAttributes methodAttributes = (exposeMode == ExposeMode.ImplementExplicit ? MethodAttributes.Private : MethodAttributes.Public); if (exposeMode == ExposeMode.ImplementImplicit || exposeMode == ExposeMode.ImplementExplicit) methodAttributes |= MethodAttributes.Final; methodAttributes |= MethodAttributes.HideBySig; if (semanticAttributes != MethodSemanticsAttributes.None) methodAttributes |= MethodAttributes.SpecialName; if (exposeMode == ExposeMode.ImplementImplicit || exposeMode == ExposeMode.ImplementExplicit) methodAttributes |= MethodAttributes.NewSlot | MethodAttributes.Virtual; var method = new MethodDefinition(name, methodAttributes, (methodToExposeWithResolvedGenerics ?? methodToExpose).ReturnType); foreach (var genericParameter in (methodToExposeWithResolvedGenerics ?? methodToExpose).GenericParameters) { method.GenericParameters.Add(new GenericParameter(genericParameter.Name, method)); } foreach (var parameter in (methodToExposeWithResolvedGenerics ?? methodToExpose).Parameters) { method.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes, parameter.ParameterType)); } var existingMethod = typeToProcess.GetMethodLike(method); if (existingMethod != null) return existingMethod; bool methodReturnsVoid = method.ReturnType.FullName == ModuleDefinition.TypeSystem.Void.FullName; if (!methodReturnsVoid) { method.Body.Variables.Add(new VariableDefinition(method.ReturnType)); method.Body.InitLocals = true; } var instructions = method.Body.Instructions; instructions.Add(Instruction.Create(OpCodes.Nop)); instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); // Load this instructions.Add(Instruction.Create(OpCodes.Ldfld, fieldToProcess.DeclaringType.HasGenericParameters ? fieldToProcess.With(declaringType: fieldToProcess.DeclaringType.MakeGenericInstanceTypeWithGenericParametersAsGenericArguments()) : fieldToProcess) ); if (methodToExpose.Parameters.Count >= 1) instructions.Add(Instruction.Create(OpCodes.Ldarg_1)); if (methodToExpose.Parameters.Count >= 2) instructions.Add(Instruction.Create(OpCodes.Ldarg_2)); if (methodToExpose.Parameters.Count >= 3) instructions.Add(Instruction.Create(OpCodes.Ldarg_3)); if (methodToExpose.Parameters.Count >= 4) { for (var i = 3; i < methodToExpose.Parameters.Count; i++) { instructions.Add(Instruction.Create(OpCodes.Ldarg_S, i + 1)); } } instructions.Add(Instruction.Create(OpCodes.Callvirt, methodToExpose.HasGenericParameters ? methodToExpose.MakeGenericInstanceMethod(method.GenericParameters.ToArray()) : methodToExpose)); if (methodReturnsVoid) instructions.Add(Instruction.Create(OpCodes.Nop)); else { instructions.Add(Instruction.Create(OpCodes.Stloc_0)); var inst = Instruction.Create(OpCodes.Ldloc_0); instructions.Add(Instruction.Create(OpCodes.Br_S, inst)); instructions.Add(inst); } instructions.Add(Instruction.Create(OpCodes.Ret)); if (exposeMode == ExposeMode.ImplementExplicit) method.Overrides.Add(methodToExpose); AddFodyGeneratedAttributes(method); typeToProcess.Methods.Add(method); return method; }