Exemplo n.º 1
0
        public static DynamicMethod CreatePatchedMethod(MethodBase original, List <MethodInfo> prefixes, List <MethodInfo> postfixes, List <IILProcessor> processors)
        {
            var idx               = prefixes.Count() + postfixes.Count();
            var patch             = DynamicTools.CreateDynamicMethod(original, "_Patch" + idx);
            var il                = patch.GetILGenerator();
            var originalVariables = DynamicTools.DeclareLocalVariables(original, il);
            var resultVariable    = DynamicTools.DeclareReturnVar(original, il);

            // TODO: this is broken because it has only one var for all patches together.
            //       to make this useful, we need one var for each patch pair
            var privateStateVariable = DeclarePrivateStateVar(il);

            var privateVars = new Dictionary <string, LocalBuilder>();

            privateVars[RESULT_VAR] = resultVariable;
            privateVars[STATE_VAR]  = privateStateVariable;

            var afterOriginal1 = il.DefineLabel();
            var afterOriginal2 = il.DefineLabel();

            AddPrefixes(il, original, prefixes, privateVars, afterOriginal2);

            var copier = new MethodCopier(original, patch, originalVariables);

            foreach (var processor in processors)
            {
                copier.AddReplacement(processor);
            }
            copier.AddReplacement(new RetToBrAfterProcessor(afterOriginal1));
            copier.Emit();
            il.MarkLabel(afterOriginal1);
            if (resultVariable != null)
            {
                il.Emit(OpCodes.Stloc, resultVariable);
            }
            il.MarkLabel(afterOriginal2);

            AddPostfixes(il, original, postfixes, privateVars);

            if (resultVariable != null)
            {
                il.Emit(OpCodes.Ldloc, resultVariable);
            }
            il.Emit(OpCodes.Ret);

            DynamicTools.PrepareDynamicMethod(patch);
            return(patch);
        }
Exemplo n.º 2
0
        public static DynamicMethod CreatePatchedMethod(MethodBase original, List <MethodInfo> prefixes, List <MethodInfo> postfixes, List <ICodeProcessor> processors)
        {
            if (MethodCopier.DEBUG_OPCODES)
            {
                FileLog.Log("PATCHING " + original.DeclaringType + " " + original);
            }

            var idx               = prefixes.Count() + postfixes.Count();
            var patch             = DynamicTools.CreateDynamicMethod(original, "_Patch" + idx);
            var il                = patch.GetILGenerator();
            var originalVariables = DynamicTools.DeclareLocalVariables(original, il);
            var resultVariable    = DynamicTools.DeclareLocalVariable(il, AccessTools.GetReturnedType(original));

            var privateVars = new Dictionary <string, LocalBuilder>();

            privateVars[RESULT_VAR] = resultVariable;
            prefixes.ForEach(prefix =>
            {
                prefix.GetParameters()
                .Where(patchParam => patchParam.Name == STATE_VAR)
                .Do(patchParam =>
                {
                    var privateStateVariable = DynamicTools.DeclareLocalVariable(il, patchParam.ParameterType);
                    privateVars[prefix.DeclaringType.FullName] = privateStateVariable;
                });
            });

            var afterOriginal1 = il.DefineLabel();
            var afterOriginal2 = il.DefineLabel();
            var canHaveJump    = AddPrefixes(il, original, prefixes, privateVars, afterOriginal2);

            var copier = new MethodCopier(original, patch, originalVariables);

            foreach (var processor in processors)
            {
                copier.AddReplacement(processor);
            }
            copier.AddReplacement(new RetToBrAfterProcessor(afterOriginal1));
            copier.Emit();
            Emitter.MarkLabel(il, afterOriginal1);
            if (resultVariable != null)
            {
                Emitter.Emit(il, OpCodes.Stloc, resultVariable);
            }
            if (canHaveJump)
            {
                Emitter.MarkLabel(il, afterOriginal2);
            }

            AddPostfixes(il, original, postfixes, privateVars);

            if (resultVariable != null)
            {
                Emitter.Emit(il, OpCodes.Ldloc, resultVariable);
            }
            Emitter.Emit(il, OpCodes.Ret);

            if (MethodCopier.DEBUG_OPCODES)
            {
                FileLog.Log("DONE");
                FileLog.Log("");
            }

            DynamicTools.PrepareDynamicMethod(patch);
            return(patch);
        }