Created
April 25, 2020 11:35
-
-
Save pardeike/45196a8b8ef331f38b14e1a7e5ee1782 to your computer and use it in GitHub Desktop.
Calling a base method from a patch is hard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// run this from LINQPad | |
// don't forget to add the dependencies to Harmony | |
void Main() | |
{ | |
var harmony = new Harmony("test"); | |
harmony.PatchAll(); | |
var bar = new Bar(); | |
Prefix(bar); | |
// will print | |
// Bar.Test(1) | |
// Bar.Test(2) | |
// Bar.Test(3) | |
// Bar.Test(4) | |
// Bar.Test(5) | |
// Foo.Test(6) | |
} | |
[HarmonyPatch(typeof(Foo), "Test")] | |
class Patch | |
{ | |
[HarmonyReversePatch] | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static void Test(Foo instance, string s) | |
{ | |
Console.WriteLine($"Patch.Test({instance}, {s})"); | |
} | |
} | |
static MethodInfo mTest = typeof(Foo).GetMethod("Test"); | |
static FastInvokeHandler Test = MethodInvoker.GetHandler(mTest, true); | |
delegate void TestDelegate(Foo instance, string s); | |
static TestDelegate dTest = (TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate), mTest); | |
public void Prefix(Bar bar) | |
{ | |
// normal call | |
bar.Test("1"); | |
// casting does not work | |
((Foo)bar).Test("2"); | |
// simple invoke does not work | |
mTest.Invoke(bar, new[] { "3" }); | |
// FastInvokeHandler does not work | |
Test(bar, new[] { "4" }); | |
// delegate does not work | |
dTest(bar, "5"); | |
// Reverse patch works | |
Patch.Test(bar, "6"); | |
} | |
public class Foo | |
{ | |
public virtual void Test(string s) | |
{ | |
Console.WriteLine($"Foo.Test({s})"); | |
} | |
} | |
public class Bar : Foo | |
{ | |
public override void Test(string s) | |
{ | |
Console.WriteLine($"Bar.Test({s})"); | |
} | |
} |
In line 26, you just define your dummy to be the same as the original. If your original has a return value then your dummy would too.
Having a similar issue, but the base class thing i'm trying to access is a protected property. Not sure how to deal with that.
Properties are just methods. You adapt the annotations of the reverse patch according to the documentation to specify a property.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Would love to see an example where the base method returns a value instead of just being void -- haven't figured out how to get that to work right.