1 /* https://stackoverflow.com/questions/7299097/dynamically-replace-the-contents-of-a-c-sharp-method 2 For .NET 4 and above 3 4 "C:Program Files (x86)MSBuild14.0Bincsc.exe" /unsafe+ /out:replacemethod.exe replacemethod.cs && start "replacemethod.exe" replacemethod.exe 5 PrintInfo: Version x64 Release 6 7 1. Replace Instance Method Class1.Demo() 8 Demo 9 Replace result: True 10 Foo 11 12 2. Replace Instance Overload of Method Class1.Demo(10) 13 Demo: 10 14 Replace result: True 15 Foo: 10 16 17 3. Replace Static Method Class1.DemoStatic() 18 DemoStatic 19 Replace result: True 20 FooStatic 21 22 Press any key to EXIT... 23 */ 24 25 using System; 26 using System.Reflection; 27 using System.Runtime.CompilerServices; 28 29 class Program { 30 public static void Main(params string[] args){ 31 PrintInfo(); 32 Console.WriteLine(); 33 34 Test(); 35 36 Console.Write(" Press any key to EXIT..."); 37 Console.ReadKey(true); 38 } 39 40 public static void PrintInfo() { 41 Console.Write("PrintInfo: "); 42 if (IntPtr.Size == 4) { 43 #if DEBUG 44 Console.WriteLine("Version x86 Debug"); 45 #else 46 Console.WriteLine("Version x86 Release"); 47 #endif 48 } else { 49 #if DEBUG 50 Console.WriteLine("Version x64 Debug"); 51 #else 52 Console.WriteLine("Version x64 Release"); 53 #endif 54 } 55 } 56 57 public static void Test() { 58 Console.WriteLine("1. Replace Instance Method Class1.Demo()"); 59 var o = new Class1(); 60 o.Demo(); 61 var r = CSharpUtils.ReplaceMethod(typeof(Class1), "Demo", typeof(Program), "Foo"); 62 Console.WriteLine("Replace result: {0}", r); 63 o.Demo(); 64 65 Console.WriteLine(); 66 67 Console.WriteLine("2. Replace Instance Overload of Method Class1.Demo(10)"); 68 o.Demo(10); 69 r = CSharpUtils.ReplaceMethod(typeof(Class1), "Demo", typeof(Program), "Foo", types:new Type[]{ typeof(int) }); 70 Console.WriteLine("Replace result: {0}" ,r); 71 o.Demo(10); 72 73 Console.WriteLine(); 74 75 Console.WriteLine("3. Replace Static Method Class1.DemoStatic()"); 76 Class1.DemoStatic(); 77 r = CSharpUtils.ReplaceMethod(typeof(Class1), "DemoStatic", typeof(Program), "FooStatic", BindingFlags.Static|BindingFlags.NonPublic|BindingFlags.Public); 78 Console.WriteLine("Replace result: {0}" ,r); 79 Class1.DemoStatic(); 80 } 81 82 private void Foo() { 83 Console.WriteLine("Foo"); 84 } 85 86 private void Foo(int d) { 87 Console.WriteLine("Foo: {0}", d); 88 } 89 90 private static void FooStatic() { 91 Console.WriteLine("FooStatic"); 92 } 93 } 94 95 96 class Class1 { 97 public void Demo() { 98 Console.WriteLine("Demo"); 99 } 100 101 public void Demo(int d) { 102 Console.WriteLine("Demo: {0}", d); 103 } 104 105 public static void DemoStatic() { 106 Console.WriteLine("DemoStatic"); 107 } 108 } 109 110 111 public static class CSharpUtils { 112 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) { 113 if (types == null) { 114 types = Type.EmptyTypes; 115 } 116 MethodInfo tarMethod = targetType.GetMethod(targetMethod, bindingAttr, binder, callConvention, types, modifiers); 117 MethodInfo injMethod = injectType.GetMethod(injectMethod, bindingAttr, binder, callConvention, types, modifiers); 118 if (tarMethod == null || injMethod == null) { 119 return false; 120 } 121 RuntimeHelpers.PrepareMethod(tarMethod.MethodHandle); 122 RuntimeHelpers.PrepareMethod(injMethod.MethodHandle); 123 unsafe { 124 if (IntPtr.Size == 4) { 125 int* tar = (int*)tarMethod.MethodHandle.Value.ToPointer() + 2; 126 int* inj = (int*)injMethod.MethodHandle.Value.ToPointer() + 2; 127 *tar = *inj; 128 } else { 129 long* tar = (long*)tarMethod.MethodHandle.Value.ToPointer() + 1; 130 long* inj = (long*)injMethod.MethodHandle.Value.ToPointer() + 1; 131 *tar = *inj; 132 } 133 } 134 return true; 135 } 136 }