У меня есть функция для замены тела функции динамической c функцией. Функция для замены тела функции взята из следующих ответов SO [ Link 1 , Link 2 ].
Моя функция выглядит так:
public static class Helper
{
public static unsafe void SetMethod(MethodInfo toReplace, MethodInfo toInject)
{
// Parameter validations...
// Prepare methods
RuntimeHelpers.PrepareMethod(toReplace.MethodHandle);
RuntimeHelpers.PrepareMethod(toInject.MethodHandle);
// For simplicity, we use only a nonvirtual method and a
// pointer size of non 8
if (toReplace.IsVirtual){ // Handle virtual method }
else
{
if (IntPtr.Size == 4){ // Handle pointer size of 4 }
{
long* inj = (long*)b.MethodHandle.Value.ToPointer() + 1;
long* tar = (long*)a.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
// Version x64 Debug
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
// Version x64 Release
*tar = *inj;
#endif
}
}
}
}
До сих пор работают следующие случаи:
public static class UnitTestsClass
{
public static int GetTables(string somename)
{
return 12 + somename.Length;
}
}
public static class ClassToInject
{
public static int GetTables(string somename)
{
return 1;
}
}
// Case: Replace with other function
public void Test1()
{
var replaceFunc = typeof(UnitTestsClass).GetMethod("GetTables");
var injectFunc = typeof(ClassToInject).GetMethod("GetTables");
Helper.SetMethod(replaceFunc, injectFunc);
}
// Case: Replace with Func<>
public void Test2()
{
var replaceFunc = typeof(UnitTestsClass).GetMethod("GetTables");
Func<string, int> injectFunc = x => 2;
Helper.SetMethod(replaceFunc, injectFunc.Method);
}
Но следующий случай с использованием лямбда-выражения isn ' пока не работает. SetMethod
выдает ошибку
Запрошенная операция недопустима для DynamicMethod
в методе RuntimeHelpers.PrepareMethod
. Если я закомментирую метод, я получаю ошибку
Запрошенная операция недопустима для DynamicMethod
снова, когда он пытается получить указатель на метод.
// Case: Replace with lambda expression
public void Test3()
{
var replaceFunc = typeof(UnitTestsClass).GetMethod("GetTables");
Expression<Func<string, int>> injectExpression = x => 2;
Func<string, int> injectFunc = injectExpression.Compile();
Helper.SetMethod(replaceFunc, injectFunc.Method);
}
Кто-нибудь может мне помочь заменить тело функции на функцию лямбда-выражения?