mirror of
https://github.com/pardeike/Harmony
synced 2026-06-08 16:40:38 +00:00
95 lines
2.3 KiB
C#
95 lines
2.3 KiB
C#
namespace Reverse_Patching
|
|
{
|
|
using HarmonyLib;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Reflection.Emit;
|
|
|
|
public class Example
|
|
{
|
|
// <example>
|
|
private class OriginalCode
|
|
{
|
|
private void Test(int counter, string name)
|
|
{
|
|
// ...
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch]
|
|
public class Patch
|
|
{
|
|
[HarmonyReversePatch]
|
|
[HarmonyPatch(typeof(OriginalCode), "Test")]
|
|
public static void MyTest(object instance, int counter, string name) =>
|
|
// its a stub so it has no initial content
|
|
throw new NotImplementedException("It's a stub");
|
|
}
|
|
|
|
class Main
|
|
{
|
|
void Test() =>
|
|
// here we call OriginalCode.Test()
|
|
Patch.MyTest(originalInstance, 100, "hello");
|
|
}
|
|
// </example>
|
|
|
|
public static object originalInstance;
|
|
}
|
|
|
|
class TranspilerExample
|
|
{
|
|
// <transpiler>
|
|
private class OriginalClass
|
|
{
|
|
private string SpecialCalculation(string original, int n)
|
|
{
|
|
var parts = original.Split('-');
|
|
var str = string.Join("", parts) + n;
|
|
return str + "Prolog";
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch]
|
|
public class Patch
|
|
{
|
|
// When reverse patched, StringOperation will contain all the
|
|
// code from the original including the Join() but not the +n
|
|
//
|
|
// Basically
|
|
// var parts = original.Split('-');
|
|
// return string.Join("", parts)
|
|
//
|
|
[HarmonyReversePatch]
|
|
[HarmonyPatch(typeof(OriginalClass), "SpecialCalculation")]
|
|
public static string StringOperation(string original)
|
|
{
|
|
// This inner transpiler will be applied to the original and
|
|
// the result will replace this method
|
|
//
|
|
// That will allow this method to have a different signature
|
|
// than the original and it must match the transpiled result
|
|
//
|
|
IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
|
{
|
|
var list = Transpilers.Manipulator(instructions,
|
|
item => item.opcode == OpCodes.Ldarg_1,
|
|
item => item.opcode = OpCodes.Ldarg_0
|
|
).ToList();
|
|
var mJoin = SymbolExtensions.GetMethodInfo(() => string.Join(null, null));
|
|
var idx = list.FindIndex(item => item.opcode == OpCodes.Call && item.operand as MethodInfo == mJoin);
|
|
list.RemoveRange(idx + 1, list.Count - (idx + 1));
|
|
return list.AsEnumerable();
|
|
}
|
|
|
|
// make compiler happy
|
|
_ = Transpiler(null);
|
|
return original;
|
|
}
|
|
}
|
|
// </transpiler>
|
|
}
|
|
}
|