An add-on library for Harmony, that allows patching of enumerator methods.
Since Harmony v2.2.1.0, this library is no longer needed for patching Enumerators.
You can now specify a new MethodType in the HarmonyPatch-Attribute constructor to patch Enumerators
Example:
[HarmonyPatch(typeof(ClassWithEnumeratorMethod), nameof(SomeEnumeratorMethod), MethodType.Enumerator)]One annoying limitation of Harmony, is that it currently does not support patching Enumerator methods properly.
Enumerator methods are more complicated beneath the surface than they appear, as they just return an object of a hidden class which does all the work.
Consensus redirects a Harmony patch from the normal enumerator method to its internal Current property or MoveNext method instead.
- The
__instancevariable ofPrefixandPostfixmethods receives the underlying Enumerator object instead of the object where the Enumerator was defined.
Add 0Harmony.dll from Harmony or HarmonyX to the lib directory to build it.
After you have created your Harmony instance, you need to pass it to ConsensusPatcher.Patch before patching anything.
Harmony harmonyInstance = new Harmony("your.harmony.id");
ConsensusPatcher.Patch(harmonyInstance);
harmonyInstance.PatchAll();You can add the [Consensus] attribute to an existing harmony patch attribute.
The attribute takes an optional parameter, which chooses whether the patch should be redirected to the Current property or the MoveNext method.
The attribute without parameters will always redirect to the MoveNext method.
[Consensus(PatchEnumerator.MoveNext)]
[HarmonyPatch(typeof(ClassWithEnumeratorMethod), nameof(SomeEnumeratorMethod))]
internal class SomeEnumeratorMethodPatch
{
...
}Check the ConsensusTest project for a real example.
If you want to patch a enumerator method manually, then you can use the GetCurrent and GetMoveNext helper methods of the ConsensusPatcher class.
Harmony harmonyInstance = new Harmony("your.harmony.id");
MethodInfo original = AccessTools.Method(typeof(ClassWithEnumeratorMethod), nameof(SomeEnumeratorMethod));
MethodInfo prefix = AccessTools.Method(typeof(SomeEnumeratorMethodPatch), nameof(SomeEnumeratorMethodPrefix));
MethodInfo postfix = AccessTools.Method(typeof(SomeEnumeratorMethodPatch), nameof(SomeEnumeratorMethodPostfix));
MethodInfo transpiler = AccessTools.Method(typeof(SomeEnumeratorMethodPatch), nameof(SomeEnumeratorMethodTranspiler));
harmonyInstance.Patch(ConsensusPatcher.GetMoveNext(original), new HarmonyMethod(prefix), new HarmonyMethod(postfix), new HarmonyMethod(transpiler));Check the ConsensusTest project for a real example.
- .NET Standard 2.0
- Visual Studio 2019
- C# 9