/* https://*.com/questions/7299097/dynamically-replace-the-contents-of-a-c-sharp-method
For .NET 4 and above "C:\Program Files (x86)\MSBuild\14.0\Bin\csc.exe" /unsafe+ /out:replacemethod.exe replacemethod.cs && start "replacemethod.exe" replacemethod.exe
PrintInfo: Version x64 Release 1. Replace Instance Method Class1.Demo()
Demo
Replace result: True
Foo 2. Replace Instance Overload of Method Class1.Demo(10)
Demo: 10
Replace result: True
Foo: 10 3. Replace Static Method Class1.DemoStatic()
DemoStatic
Replace result: True
FooStatic Press any key to EXIT...
*/ using System;
using System.Reflection;
using System.Runtime.CompilerServices; class Program {
public static void Main(params string[] args){
PrintInfo();
Console.WriteLine(); Test(); Console.Write("\nPress any key to EXIT...");
Console.ReadKey(true);
} public static void PrintInfo() {
Console.Write("PrintInfo: ");
if (IntPtr.Size == ) {
#if DEBUG
Console.WriteLine("Version x86 Debug");
#else
Console.WriteLine("Version x86 Release");
#endif
} else {
#if DEBUG
Console.WriteLine("Version x64 Debug");
#else
Console.WriteLine("Version x64 Release");
#endif
}
} public static void Test() {
Console.WriteLine("1. Replace Instance Method Class1.Demo()");
var o = new Class1();
o.Demo();
var r = CSharpUtils.ReplaceMethod(typeof(Class1), "Demo", typeof(Program), "Foo");
Console.WriteLine("Replace result: {0}", r);
o.Demo(); Console.WriteLine(); Console.WriteLine("2. Replace Instance Overload of Method Class1.Demo(10)");
o.Demo();
r = CSharpUtils.ReplaceMethod(typeof(Class1), "Demo", typeof(Program), "Foo", types:new Type[]{ typeof(int) });
Console.WriteLine("Replace result: {0}" ,r);
o.Demo(); Console.WriteLine(); Console.WriteLine("3. Replace Static Method Class1.DemoStatic()");
Class1.DemoStatic();
r = CSharpUtils.ReplaceMethod(typeof(Class1), "DemoStatic", typeof(Program), "FooStatic", BindingFlags.Static|BindingFlags.NonPublic|BindingFlags.Public);
Console.WriteLine("Replace result: {0}" ,r);
Class1.DemoStatic();
} private void Foo() {
Console.WriteLine("Foo");
} private void Foo(int d) {
Console.WriteLine("Foo: {0}", d);
} private static void FooStatic() {
Console.WriteLine("FooStatic");
}
} class Class1 {
public void Demo() {
Console.WriteLine("Demo");
} public void Demo(int d) {
Console.WriteLine("Demo: {0}", d);
} public static void DemoStatic() {
Console.WriteLine("DemoStatic");
}
} public static class CSharpUtils {
public static bool ReplaceMethod(Type targetType, string targetMethod, Type injectType, string injectMethod, BindingFlags bindingAttr = BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public, Binder binder = null, CallingConventions callConvention = CallingConventions.Any, Type[] types = null, ParameterModifier[] modifiers = null) {
if (types == null) {
types = Type.EmptyTypes;
}
MethodInfo tarMethod = targetType.GetMethod(targetMethod, bindingAttr, binder, callConvention, types, modifiers);
MethodInfo injMethod = injectType.GetMethod(injectMethod, bindingAttr, binder, callConvention, types, modifiers);
if (tarMethod == null || injMethod == null) {
return false;
}
RuntimeHelpers.PrepareMethod(tarMethod.MethodHandle);
RuntimeHelpers.PrepareMethod(injMethod.MethodHandle);
unsafe {
if (IntPtr.Size == ) {
int* tar = (int*)tarMethod.MethodHandle.Value.ToPointer() + ;
int* inj = (int*)injMethod.MethodHandle.Value.ToPointer() + ;
*tar = *inj;
} else {
long* tar = (long*)tarMethod.MethodHandle.Value.ToPointer() + ;
long* inj = (long*)injMethod.MethodHandle.Value.ToPointer() + ;
*tar = *inj;
}
}
return true;
}
}