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
Section titled “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. [MonoDetourHookInitialize] 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 MonoDetourHookInitialize
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 MonoDetourHookInitialize and invokes them. MonoDetourManager.InvokeHookInitializers(Assembly.GetExecutingAssembly());}
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
Section titled “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
Section titled “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.