将代码动态附加到方法 .Net-Core

joh*_*y 5 5 c# reflection emit

我对在 .Net-Core 中动态附加代码很感兴趣。 注意:这仅用于教育目的。

目前我有一个交换方法的类:

public static void Inject<TTarget, TInject>(string targetFuncName, string injectFuncName)
{
    MethodInfo methodToReplace = typeof(TTarget).GetMethod(targetFuncName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
    MethodInfo methodToInject = typeof(TInject).GetMethod(injectFuncName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
    RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
    RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);

    unsafe
    {
        if (IntPtr.Size == 4)
        {
            int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
            int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
            Console.WriteLine("\nVersion x86 Debug\n");

            byte* injInst = (byte*)*inj;
            byte* tarInst = (byte*)*tar;

            int* injSrc = (int*)(injInst + 1);
            int* tarSrc = (int*)(tarInst + 1);

            *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
            Console.WriteLine("\nVersion x86 Release\n");
            *tar = *inj;
#endif
        }
        else
        {
            long* inj = (long*)methodToInject.MethodHandle.Value.ToPointer() + 1;
            long* tar = (long*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
            Console.WriteLine("\nVersion x64 Debug\n");
            byte* injInst = (byte*)*inj;
            byte* tarInst = (byte*)*tar;

            int* injSrc = (int*)(injInst + 1);
            int* tarSrc = (int*)(tarInst + 1);

            *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
 #else
            Console.WriteLine("\nVersion x64 Release\n");
            *tar = *inj;
#endif
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码很好地交换了方法,但是,如果您正在调试,则似乎永远不会命中原始代码。相反,我想交换方法字节中的返回语句,并将其替换为跳转到具有相同参数的另一个函数的语句。

但是,.Net Core 目前不支持MethodRental.SwapMethodBody 如何将代码动态附加到函数的末尾?

joh*_*y 5 0

我想出了一个作弊的方法来做到这一点。我还没有写出所有的代码,但我会用伪代码解释

假设我们有一个方法:

public class ValuesController: ControllerBase
{
    [HttpGet("Seven")]
    public int Seven(string id)
    {
        return 7;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们想用另一种方法交换它

public int Eight(int retValue)
{
    return retValue + 1;
}
Run Code Online (Sandbox Code Playgroud)

我们可以在动态程序集中生成一个Func。看起来像这样:

public int Dummy(string id)
{}

public int DummyFuncContainer(string id)
{
    var result = Dummy(id);
    return Eight(result);
}
Run Code Online (Sandbox Code Playgroud)

那么你需要做的就是。

Dummy()方法与我们想要的 func交换Seven(),然后将Seven()(现在指向Dummy())与交换DummyFuncContainer()

编辑:抱歉需要澄清,您只需要获取这样的方法即可通过此操作。目前我面前没有完整的示例。

var methodToReplace = typeof(ValuesController).GetMethod("Seven", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
        
Run Code Online (Sandbox Code Playgroud)