8

标题或多或少说明了一切。基于这篇文章,我想出了这个:

public static unsafe void Replace(this MethodBase destination, MethodBase source)
{
    IntPtr srcHandle = source.MethodHandle.GetFunctionPointer();
    IntPtr dstHandle = destination.MethodHandle.GetFunctionPointer();

    int* dstPtr = (int*)dstHandle.ToPointer();
    *dstPtr = srcHandle.ToInt32();
}

这实际上有效......偶尔-.-

例如,这有效。

public static class Program
{
    public static void Main(string[] args)
    {
        MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static);
        MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static);

        methodA.Replace(methodB);

        A();
        B();
    }

    public static void A()
    {
        Console.WriteLine("Hai World");
    }

    public static void B()
    {
        Console.WriteLine("Bai World");
    }
}

但是,这不是(SEHException)。我所做的只是改变定义函数的顺序。

public static class Program
{
    public static void Main(string[] args)
    {
        MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static);
        MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static);

        methodA.Replace(methodB);

        A();
        B();
    }

    public static void B()
    {
        Console.WriteLine("Bai World");
    }

    public static void A()
    {
        Console.WriteLine("Hai World");
    }
}

至于文章中的代码......我根本无法让它工作。

有什么想法/替代方案吗?

4

1 回答 1

7

这是在做出很多糟糕的假设,会让你大吃一惊。

首先,通过反射返回的结构不能以任何方式保证指向任何运行时结构。因此,试图修改它包含或返回的指针是完全错误的。

其次,如果您希望执行诸如注入前/后方法调用不变量之类的操作(例如),那么您可能应该构造运行时代理对象并注入它们。或者通过 Emit 命名空间使用动态方法构造。试图通过未记录/未知的行为(例如上面的代码)来操纵事物是行不通的。

您还需要意识到 JIT 决定何时运行。有时它针对整个类运行,有时它只针对单个方法运行。您的代码没有尝试确定该方法是否已经被 JITted,并且盲目地假设返回的函数指针可以被修改。

于 2011-01-29T22:20:05.500 回答