Browse documentation

Prepare, target, and clean up

Annotation patch classes can define helpers to prepare and clean up patching, or choose target methods in code.

Helpers accept these optional arguments, matched by type rather than name:

  • MethodBase original - the current original being patched
  • Harmony harmony - the current Harmony instance
  • Exception ex - only valid in Cleanup and receives a possible exception

Here is a simple example that patches a method inside a private type:

[HarmonyPatch] // at least one Harmony annotation makes Harmony not skip this patch class when calling PatchAll()
class MyPatch
{
    // here, inside the patch class, you can place the auxiliary patch methods
    // for example TargetMethod:

    public static MethodBase TargetMethod()
    {
        // use normal reflection or helper methods in <AccessTools> to find the method/constructor
        // you want to patch and return its MethodInfo/ConstructorInfo
        //
        var type = AccessTools.FirstInner(typeof(TheClass), t => t.Name.Contains("Stuff"));
        return AccessTools.FirstMethod(type, method => method.Name.Contains("SomeMethod"));
    }

    // your patches
    public static void Prefix()
    {
        // ...
    }
}

Prepare

Harmony looks for a preparation method with one of these forms:

static void Prepare(...)
static void Prepare(MethodBase original, ...)
static bool Prepare(MethodBase original, ...)
// or
[HarmonyPrepare]
static void MyInitializer(...)
static void MyInitializer(MethodBase original, ...)
static bool MyInitializer(MethodBase original, ...)

Prepare runs first with original = null for the whole class, then for each target method. Returning false skips the class or that target, respectively.

TargetMethod

To choose the target in code instead of annotations, define:

static MethodBase TargetMethod(...)
// or
[HarmonyTargetMethod]
static MethodBase CalculateMethod(...)

Return the target's MethodBase, never null. Use Prepare() to skip patching conditionally.

TargetMethods

To apply the same patches to several targets, return an enumeration of MethodBase:

static IEnumerable<MethodBase> TargetMethods(...)
// or
[HarmonyTargetMethods]
static IEnumerable<MethodBase> CalculateMethods(...)

A typical implementation would yield the results like this:

static IEnumerable<MethodBase> TargetMethods()
{
    // if possible use nameof() or SymbolExtensions.GetMethodInfo() here
    yield return AccessTools.Method(typeof(Foo), "Method1");
    yield return AccessTools.Method(typeof(Bar), "Method2");

    // you could also iterate using reflections over many methods
}

Do not use an empty enumeration to skip patching; use Prepare() instead.

Cleanup

For cleanup after patching, define:

static void Cleanup(...)
static void Cleanup(MethodBase original, ...)
static Exception Cleanup(MethodBase original, ...)
// or
[HarmonyCleanup]
static void MyCleanup(...)
static void MyCleanup(MethodBase original, ...)
static Exception MyCleanup(MethodBase original, ...)

Cleanup runs after each target, then once for the whole class with original = null.

Inject Exception to inspect a patching failure; a HarmonyException may provide more details. Return an exception to replace it, or null to suppress it.

Harmony 3 preview

For the stable release, read the 2.x documentation.