NuGet 安装:
dotnet add package Lib.Harmony
或在 VS 的 NuGet 管理器里搜 Lib.Harmony
public class Calculator
{
public int Add(int a, int b)
{
Console.WriteLine("原始 Add 被调用");
return a + b;
}
}
using HarmonyLib;
[HarmonyPatch(typeof(Calculator))]
[HarmonyPatch(nameof(Calculator.Add))]
public class CalculatorPatch
{
// Prefix:方法执行前
static void Prefix(int a, int b)
{
Console.WriteLine($"Prefix:a={a}, b={b}");
}
// Postfix:方法执行后
static void Postfix(int __result)
{
Console.WriteLine($"Postfix:结果={__result}");
}
}
⚠️ 关键点:
__result 是 Harmony 的魔法参数staticusing HarmonyLib;
class Program
{
static void Main()
{
var harmony = new Harmony("com.xfe.demo.patch");
harmony.PatchAll();
var calc = new Calculator();
Console.WriteLine(calc.Add(2, 3));
}
}
输出顺序:
Prefix:a=2, b=3
原始 Add 被调用
Postfix:结果=5
5
boolfalse = 跳过原方法static bool Prefix(ref int __result)
{
__result = 999;
return false; // 原方法不会执行
}
👉 直接“接管”原方法
static void Postfix(ref int __result)
{
__result *= 2;
}
👉 直接改 IL 指令
using System.Reflection.Emit;
static IEnumerable<CodeInstruction> Transpiler(
IEnumerable<CodeInstruction> instructions)
{
foreach (var ins in instructions)
{
yield return ins;
}
}
⚠️ 这个一般只在:
[HarmonyPatch(typeof(MyClass), "PrivateMethod")]
[HarmonyPatch(typeof(MyClass))]
[HarmonyPatch("Do")]
[HarmonyPatch(new Type[] { typeof(int), typeof(string) })]
Patch 写法一样,不用特殊处理
| 参数名 | 作用 |
|---|---|
__instance |
当前对象实例 |
__result |
返回值 |
__state |
Prefix → Postfix 传递数据 |
__originalMethod |
原始 MethodInfo |
__args |
所有参数数组 |
static void Prefix(ref long __state)
{
__state = Stopwatch.GetTimestamp();
}
static void Postfix(long __state)
{
Console.WriteLine("耗时:" + __state);
}
var harmony = new Harmony("xfe.single.patch");
var original = AccessTools.Method(
typeof(Calculator), "Add");
var prefix = new HarmonyMethod(
typeof(CalculatorPatch), "Prefix");
harmony.Patch(original, prefix);
👉 参数名、类型、ref 都要对
static👉 Patch 方法必须是 static
👉 多个 Harmony 同时 Patch,用:
[HarmonyPriority(Priority.High)]