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 Enumerator
s.
You can now specify a new MethodType
in the HarmonyPatch
-Attribute constructor to patch Enumerator
s
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
__instance
variable ofPrefix
andPostfix
methods 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