public static Action <MethodDef> ApplyInject(this MethodBase inject, PatchConfiguration patch) => stub =>
        {
            CilBody            stubBody       = stub.Body;
            MethodBody         injectBody     = inject.GetMethodBody();
            List <Instruction> originalIL     = new List <Instruction>(stubBody.Instructions);
            List <Local>       originalLocals = new List <Local>(stubBody.Variables);
            stubBody.Variables.Clear();
            foreach (LocalVariableInfo local in injectBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex))
            {
                stubBody.Variables.Add(stub.Module.ToDNLib(local));
            }
            List <Instruction> mixinIL = new CilParser(inject.Module, stubBody.Variables, injectBody.GetILAsByteArray()).Parse();
            mixinIL.SimplifyMacros(stubBody.Variables, stub.Parameters);
            IList <Instruction> newIL = stubBody.Instructions;
            newIL.Clear();
            foreach (Instruction inst in mixinIL)
            {
                switch (inst.Operand)
                {
                case FieldInfo field:
                    inst.Operand = patch.ResolveOrImport(stub.Module, field);
                    break;

                case MethodBase method:
                    if (method.IsDefined(typeof(BaseDependencyAttribute)))
                    {
                        throw new InvalidOperationException("attempt to inject a body with a base dependency call");
                    }
                    inst.Operand = patch.ResolveOrImport(stub.Module, method);
                    break;

                case Type type:
                    inst.Operand = patch.ResolveOrImport(stub.Module, type);
                    break;

                case byte[] blob:
                    throw new NotImplementedException("how do you import this?");

                case MemberInfo member:
                    throw new NotImplementedException("how do you import this?");
                }
                newIL.Add(inst);
            }
            stubBody.ExceptionHandlers.Clear();
            foreach (ExceptionHandlingClause ehc in injectBody.ExceptionHandlingClauses)
            {
                stubBody.ExceptionHandlers.Add(ehc.ToDNLib(stub.Module, newIL));
            }
            stubBody.OptimizeMacros();
        };
        public static Action <MethodDef> ApplyMixin(this MethodBase mixin, PatchConfiguration patch) => original =>
        {
            CilBody            originalBody   = original.Body;
            MethodBody         mixinBody      = mixin.GetMethodBody();
            List <Instruction> originalIL     = new List <Instruction>(originalBody.Instructions);
            List <Local>       originalLocals = new List <Local>(originalBody.Variables);
            originalBody.Variables.Clear();
            foreach (LocalVariableInfo local in mixinBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex))
            {
                originalBody.Variables.Add(original.Module.ToDNLib(local));
            }
            List <Instruction> mixinIL = new CilParser(mixin.Module, originalBody.Variables, mixinBody.GetILAsByteArray()).Parse();
            mixinIL.SimplifyMacros(originalBody.Variables, original.Parameters);
            IList <Instruction> newIL = originalBody.Instructions;
            newIL.Clear();
            int ilStart = 0;
            if (mixin.IsConstructor)
            {
                foreach (Instruction inst in mixin.IsDefined(typeof(RewriteBaseAttribute)) ? mixinIL : originalIL)
                {
                    ilStart++;
                    newIL.Add(inst);
                    if (inst.OpCode.FlowControl == FlowControl.Call)
                    {
                        break;
                    }
                }
                RemoveCall(originalIL);
                RemoveCall(mixinIL);
            }
            MethodDef baseCopy = new MethodDefUser(original.DeclaringType.FindUnusedMethodName(original.Name + "<Base>$"), original.MethodSig, original.ImplAttributes, original.Attributes & CopyMask | CopyAttr);
            bool      useBase  = false;
            foreach (Instruction inst in mixinIL)
            {
                switch (inst.Operand)
                {
                case FieldInfo field:
                    inst.Operand = patch.ResolveOrImport(original.Module, field);
                    break;

                case MethodBase method:
                    if (method.IsDefined(typeof(BaseDependencyAttribute)))
                    {
                        useBase      = true;
                        inst.Operand = baseCopy;
                        break;
                    }
                    inst.Operand = patch.ResolveOrImport(original.Module, method);
                    break;

                case Type type:
                    inst.Operand = patch.ResolveOrImport(original.Module, type);
                    break;

                case byte[] blob:
                    throw new NotImplementedException("how do you import this?");

                case MemberInfo member:
                    throw new NotImplementedException("how do you import this?");
                }
                newIL.Add(inst);
            }
            if (useBase)
            {
                baseCopy.Body = new CilBody(originalBody.InitLocals, originalIL, new List <ExceptionHandler>(originalBody.ExceptionHandlers), originalBody.Variables);
                original.DeclaringType.Methods.Add(baseCopy);
            }
            originalBody.ExceptionHandlers.Clear();
            foreach (ExceptionHandlingClause ehc in mixinBody.ExceptionHandlingClauses)
            {
                originalBody.ExceptionHandlers.Add(ehc.ToDNLib(original.Module, newIL));
            }
            originalBody.OptimizeMacros();

            void RemoveCall(List <Instruction> il)
            {
                for (int index = 0; index < il.Count; index++)
                {
                    if (il[index].OpCode.FlowControl != FlowControl.Call)
                    {
                        continue;
                    }
                    il.RemoveRange(0, index + 1);
                    break;
                }
            }
        };