Skip to content

Hooking Normal Methods

To start hooking, we need a target method we want to hook. So, given the target type and method we want to hook:

namespace Lib;
public class LibraryClass
{
public bool IsTrue { get; set; }
// We want to hook this.
public int TakeAndReturnInt(int number)
{
return number;
}
public void PrintFoo()
{
Console.WriteLine("Foo");
}
}

Let’s generate hooks for the type:

// Tell MonoDetour's HookGen to generate hooks
// for the target type.
[MonoDetourTargets(typeof(LibraryClass))]
public class LibraryClassHooks
{
// ...
}

Basic Hook

Now we can get to hooking. A simple hook we can do is:

[MonoDetourTargets(typeof(LibraryClass))]
public class LibraryClassHooks
{
// MonoDetourManager.InvokeHookInitializers will
// call methods marked with this attribute in types
// which have the MonoDetourTargetsAttribute.
[MonoDetourHookInit]
static void Init()
{
// Add a prefix hook which runs at the start of the target method.
On.Lib.LibraryClass.TakeAndReturnInt.Prefix(Prefix_TakeAndReturnInt);
}
static void Prefix_TakeAndReturnInt(LibraryClass self, ref int number)
{
// As soon as LibraryClass.TakeAndReturnInt runs,
// call its method PrintFoo with its instance.
self.PrintFoo();
// Increment the 'number' parameter by one.
number += 1;
}
}

We can either call our LibraryClassHooks.Init method manually, or use the following to call all methods marked with MonoDetourHookInit attribute that are in types marked with the MonoDetourTargets attribute:

internal static void InitAllHooks()
{
// Searches for types with MonoDetourTargets to go through and
// finds methods in them marked with MonoDetourHookInit and calls them.
DefaultMonoDetourManager.Instance.InvokeHookInitializers();
}

We can also add a hook that runs at the end of a method:

// Add a postfix hook which runs at the end of the target method.
On.Lib.LibraryClass.TakeAndReturnInt.Postfix(Postfix_TakeAndReturnInt);
// ...
static void Postfix_TakeAndReturnInt(LibraryClass self, ref int number,
ref int returnValue)
{
Console.WriteLine("Hello from postfix hook!");
}

Changing Return Value

To change a return value, your hook must be a Postfix. We can use the returnValue parameter for accessing and setting the return value.

On.Lib.LibraryClass.TakeAndReturnInt.Postfix(Postfix_TakeAndReturnInt);
static void Postfix_TakeAndReturnInt(LibraryClass self, ref int number,
ref int returnValue)
{
returnValue += 50;
}

Hooking Properties

MonoDetour.HookGen also generates hooks for properties, so this is the same case as with the basic hook example. One thing to know though is that getter methods have a get_ prefix, and setter methods have a set_ prefix.

// Hook the getter method:
On.Lib.LibraryClass.get_IsTrue.Prefix(Prefix_get_IsTrue);
// Hook the setter method:
On.Lib.LibraryClass.set_IsTrue.Prefix(Prefix_set_IsTrue);
// Note that if the property doesn't implement
// a setter, there won't be a hook for it.