예제 #1
0
        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));
            }
        }
예제 #2
0
        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();
            }
        }