C# 运行时替换方法(需要unsafe编译)

复制代码
  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)\MSBuild\14.0\Bin\csc.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("\nPress 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 }
复制代码

 

posted @   Bob-wei  阅读(1016)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示