Browse documentation

Choose a patch type

Start with the smallest change that expresses your intent. A postfix is often enough to adjust a return value; an Infix can target one operation without rewriting the surrounding instructions.

I want to… Start with Scope
Change arguments or skip a method Prefix One method invocation
Read or change a result Postfix After completion or a skip
Clean up on failure or handle an exception Finalizer The patched method and its patches
Change a selected call, field access, or other operation Infix Selected operations in an outer method
Rewrite instructions directly Transpiler The replacement body, during generation
Call a copy of an original implementation Reverse patch A stub method you control

Runtime flow

On each call · the ordinary execution path
  1. PrefixRead arguments, change them, or skip the original.
  2. OriginalRun the method body, including any instruction edits.
  3. PostfixRead or change the result after completion or a skip.
Finalizer · success or exceptionWhen installed, handles the outcome of the sequence above.

A prefix can skip the original; postfixes still run. An exception interrupts the sequence and skips remaining postfixes. A finalizer can observe, change, or suppress that exception.

Concept

To provide your own code to Harmony, define patch methods. The patch type determines when your code runs and what it can change.

Types of patches

Prefixes run before the original; postfixes run after it completes or is skipped.

Transpilers change the original's IL instructions when Harmony builds the replacement method, not on each call.

Finalizers handle exceptions from prefixes, the original, or postfixes. They can observe, replace, or suppress an exception. Without one, an exception skips the remaining patches and reaches the caller.

An Infix applies ordinary prefixes, postfixes, or finalizers to selected operations inside an outer method. It can target method/property calls, field reads or writes, construction, and literal loads. Other callers and unselected operations remain unchanged.

A reverse patch copies the original into a stub method you can call from your own code. You can also transpile that copy.

Patches need to be static

Harmony stores references to static patch methods so it can reapply everyone's patches whenever registrations change. It does not create or store patch-class instances.

Use __state for values that belong to one patched invocation and need to pass between patches in the same class. Static fields are appropriate for deliberately shared state, not independent per-call values.

Commonly unsupported use cases

Harmony patches only within the current AppDomain.

Currently, support for generic types and methods is experimental and can give unexpected results. See Edge Cases for more information.

Calls already inlined into another method can bypass your patch. See Inlining.

Patch Class

Manual patching lets you supply methods from any class. Annotation patching groups them in a patch class.

Layout The class can be public or private, static or not. Mark it with [HarmonyPatch] and describe the target using annotations. Its static patch methods use recognized names such as Prefix, or attributes such as [HarmonyPrefix]. Helper methods and fields are fine too.

Combining attributes Harmony combines the target annotations on the class with those on each patch method. For example, specify the declaring type on the class and the method name on a patch method. See combining annotations.

Patch methods

Harmony recognizes patch and helper methods by name, or by their attributes:

[HarmonyPatch(...)]
class Patch
{
	static void Prefix()
	{
		// this method uses the name "Prefix", no annotation necessary
	}

	[HarmonyPostfix]
	static void MyOwnName()
	{
		// this method is a Postfix as defined by the attribute
	}
}

For manual patching, wrap each patch's MethodInfo in a HarmonyMethod and pass it to Patch(). Method names do not matter.

note Patch methods must be static but you can define them public or private. They cannot be dynamic methods but you can write static patch factory methods that return dynamic methods.

[HarmonyPatch(...)]
class Patch
{
	// the return type of factory methods can be either MethodInfo or DynamicMethod
	[HarmonyPrefix]
	static MethodInfo PrefixFactory(MethodBase originalMethod)
	{
		// return an instance of MethodInfo or an instance of DynamicMethod
	}

	[HarmonyPostfix]
	static MethodInfo PostfixFactory(MethodBase originalMethod)
	{
		// return an instance of MethodInfo or an instance of DynamicMethod
	}
}

Method names

The patch names are Prefix, Postfix, Transpiler, and Finalizer. Annotation patching also recognizes the helpers Prepare, TargetMethod, TargetMethods, and Cleanup. Each name has a corresponding attribute, such as [HarmonyPrepare].

Patch method types

Prefixes, postfixes, and finalizers share the injected values available as parameters.

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
  • set custom state that can be recalled in the postfix
  • run code before the original

Postfix

A postfix runs after the original completes or is skipped, but not after an exception. It is commonly used to:

  • read or change the result of the original method
  • access the arguments of the original method
  • read custom state from the prefix

Transpiler

A transpiler edits the original method's IL instructions.

Finalizer

A finalizer is a method that executes after all postfixes. It wraps the original method, all prefixes, and postfixes in try/catch logic and is called either with null (no exception) or with an exception if one occurred. It is commonly used to:

  • run cleanup on success or failure
  • handle exceptions and suppress them
  • handle exceptions and alter them
Harmony 3 preview

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