zoukankan      html  css  js  c++  java
  • 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)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 }
  • 相关阅读:
    VSS與CSV區別
    办公室中节约时间
    C#中用Smtp發郵件
    关于分层结构的感悟(轉)
    Visual Studio.Net 技巧(轉)
    常用數據庫訪問方式比較
    Winows部署中一些內容說明
    适配器模式(Adapter Pattern)(轉)
    Vistual Studio 2005 sp1補丁的詳細內容
    感情 程序 祭 【转】
  • 原文地址:https://www.cnblogs.com/Bob-wei/p/7345574.html
Copyright © 2011-2022 走看看