pardeike / Harmony

A library for patching, replacing and decorating .NET and Mono methods during runtime
https://www.patreon.com/pardeike
MIT License
5.16k stars 486 forks source link

When patching a compiler generated method from a nested class, how do I declare the __instance property? #536

Closed SamuelBucher closed 1 year ago

SamuelBucher commented 1 year ago

I'm using Harmony for my RimWorld mod, and I want to patch a method called DrawExtraEyeGraphic() within PawnRenderer. Unfortunately, that method is actually a local method of DrawHeadHair(), which makes things a lot more complicated. According to dNSpy, after compilation, this translates into DrawExtraEyeGraphic() being contained within a weirdly named class <>c__DisplayClass54_0 within PawnRenderer. I know how to access and patch DrawExtraEyeGraphic():

[HarmonyPatch]
        class DrawExtraEyeGraphicPatch
        {
            public static MethodBase TargetMethod()
            {
                var type = AccessTools.FirstInner(typeof(PawnRenderer), t => t.Name.Contains("c__DisplayClass54_0"));
                return AccessTools.FirstMethod(type, method => method.Name.Contains("g__DrawExtraEyeGraphic"));
            }

            [HarmonyPrefix]
            public static bool DrawExtraEyeGraphicPrefix()
            {
                return false;
            }
        }

With this code, I successfully prevented the DrawExtraEyeGraphic() method from running. However, I actually want to replace it with a slightly modified version of itself. To do this, I need access to the fields of the compiler generated class I'm patching through __instance. Despite my searching, I couldn't find any info on how to do that. I can't just put the class's name into my code since it doesn't abide syntax. Any help?

pardeike commented 1 year ago

You use object as type and then different ways to access fields on in like FieldRef or simple reflections.

Please note that Issues are for bugs or new features in Harmony. Use the discord for support questions like this one.