标题或多或少都说明了一切。根据{{3}}文章,我想出了这个:
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");
}
}
至于文章中的代码......我根本无法使用它。
任何想法/替代品?
答案 0 :(得分:8)
这会产生许多糟糕的假设,这些假设会让你陷入困境。
首先,通过反射返回的结构无论如何都不能保证指向任何运行时结构。因此,尝试修改它包含或返回的指针是完全错误的。
其次,如果您希望执行类似注入前/后方法调用不变量(作为示例)的操作,那么您应该构造运行时代理对象并注入它们。或者通过Emit命名空间使用动态方法构造。试图通过无证/未知行为(例如上面的代码)操纵事物就不会起作用。
您还需要意识到JIT决定它何时运行。有时它会针对整个类运行,有时它只针对单个方法运行。您的代码不会尝试确定方法是否已被JIT,并且盲目地假定可以修改返回的函数指针。