Prefix
A prefix is a method that is executed before the original method. It is commonly used to:
- access and edit the arguments of the original method
- set the result of the original method
- skip the original method and prefixes that alter its input/result
- set custom state that can be recalled in the postfix
Returning false skips the original and later prefixes that Harmony considers able to affect it. A prefix returning bool, or taking writable or reference-type arguments, normally falls in that group. The injections __instance, __originalMethod, and __state are exceptions to the argument check. Other prefixes still run, as do postfixes and finalizers. This is a signature check, not an analysis of what your code does.
See the runtime flow for how prefixes, postfixes, and finalizers fit together.
Reading and changing arguments
public class OriginalCode
{
public void Test(int counter, string name)
{
// ...
}
}
[HarmonyPatch(typeof(OriginalCode), nameof(OriginalCode.Test))]
class Patch
{
static void Prefix(int counter, ref string name)
{
FileLog.Log("counter = " + counter); // read
name = "test"; // write with ref keyword
}
}
Changing the result and skipping the original
Use ref __result to supply a result, then skip the original so it does not overwrite your value. Its type must match the original return type or be assignable from it.
Return false to skip the original. Return true to let later prefixes decide whether it runs.
Skip the original when you mean to replace its behavior. For small changes, a postfix or transpiler often works better alongside other mods.
public class OriginalCode
{
public string GetName() => name; // ...
}
[HarmonyPatch(typeof(OriginalCode), nameof(OriginalCode.GetName))]
class Patch
{
static bool Prefix(ref string __result)
{
__result = "test";
return true; // make sure you only skip if really necessary
}
}
The prefix's boolean return controls execution; it is not the original method's result:
public class OriginalCode
{
public bool IsFullAfterTakingIn(int i) => DoSomeExpensiveCalculation() > i;
}
[HarmonyPatch(typeof(OriginalCode), nameof(OriginalCode.IsFullAfterTakingIn))]
class Patch
{
static bool Prefix(ref bool __result, int i)
{
if (i > 5)
{
__result = true; // any call to IsFullAfterTakingIn(i) where i > 5 now immediately returns true
return false; // skips the original and its expensive calculations
}
return true; // make sure you only skip if really necessary
}
}
Passing state between prefix and postfix
Set __state using ref or out in a prefix, then read it in a postfix. Use your own type to group several values.
Both patches must be in the same class: Harmony uses that class to identify their shared state.
public class OriginalCode
{
public void Test(int counter, string name)
{
// ...
}
}
[HarmonyPatch(typeof(OriginalCode), nameof(OriginalCode.Test))]
class Patch
{
// this example uses a Stopwatch type to measure
// and share state between prefix and postfix
static void Prefix(out Stopwatch __state)
{
__state = new Stopwatch(); // assign your own state
__state.Start();
}
static void Postfix(Stopwatch __state)
{
__state.Stop();
FileLog.Log(__state.Elapsed.ToString());
}
}