public static void RedirectConstructorFromBase(CecilContext stardewContext, Type asmType, string type, string method, Type[] parameters) { string parametersString = ""; for (int i = 0; i < parameters.Length; i++) { if (parameters[i].FullName.Contains("`")) { parametersString += ConvertGenericTypeFullNameToGenericTypeParameterFormat(parameters[i].FullName); } else { parametersString += parameters[i].FullName; } if (i != parameters.Length - 1) { parametersString += ","; } } var newConstructor = asmType.GetConstructor(parameters); if (asmType.BaseType == null) { return; } var oldConstructor = asmType.BaseType.GetConstructor(parameters); if (newConstructor == null) { return; } // Build a FullName version of newConstructor.Name string newConstructorFullName = "System.Void " + asmType.FullName + "::.ctor" + "(" + parametersString + ")"; var newConstructorReference = stardewContext.GetMethodDefinitionFullName(asmType.FullName, newConstructorFullName); if (oldConstructor == null) { return; } // Build a FullName version of oldConstructor.Name string oldConstructorFullName = "System.Void " + asmType.BaseType.FullName + "::.ctor" + "(" + parametersString + ")"; var oldConstructorReference = stardewContext.GetMethodDefinitionFullName(asmType.BaseType.FullName ?? asmType.BaseType.Namespace + "." + asmType.BaseType.Name, oldConstructorFullName); ILProcessor ilProcessor = stardewContext.GetMethodIlProcessor(type, method); var instructions = ilProcessor.Body.Instructions.Where(n => n.OpCode == OpCodes.Newobj && n.Operand == oldConstructorReference).ToList(); foreach (var instruction in instructions) { ilProcessor.Replace(instruction, ilProcessor.Create(OpCodes.Newobj, newConstructorReference)); } }
public static void RedirectConstructorToMethod(CecilContext stardewContext, Type asmType, string type, string method, string methodType, string methodName, Type[] parameters) { // Get a single string containing the full names of all parameters, comma separated string parametersString = ""; for (int i = 0; i < parameters.Length; i++) { parametersString += parameters[i].FullName; if (i != parameters.Length - 1) { parametersString += ","; } } if (asmType == null) { return; } var oldConstructor = asmType.GetConstructor(parameters); if (oldConstructor == null) { return; } // Build a FullName version of oldConstructor.Name string oldConstructorFullName = "System.Void " + asmType.FullName + "::.ctor" + "(" + parametersString + ")"; var oldConstructorReference = stardewContext.GetMethodDefinitionFullName(asmType.FullName ?? asmType.Namespace + "." + asmType.Name, oldConstructorFullName); // Build a FullName version of the new method string methodFullName = $"{asmType} {methodType}::{methodName}({parametersString})"; var newMethod = stardewContext.GetMethodDefinitionFullName(methodType, methodFullName); if (newMethod == null) { return; } ILProcessor ilProcessor = stardewContext.GetMethodIlProcessor(type, method); var instructions = ilProcessor.Body.Instructions.Where(n => n.OpCode == OpCodes.Newobj && n.Operand == oldConstructorReference).ToList(); foreach (var instruction in instructions) { ilProcessor.Body.SimplifyMacros(); ilProcessor.Replace(instruction, ilProcessor.Call(newMethod)); ilProcessor.Body.OptimizeMacros(); } }