RuntimeHelpers.PrepareMethod 使用在通用 class 中创建的 Func<string> 调用时无法正常工作
RuntimeHelpers.PrepareMethod not working when called with Func<string> created in Generic class
我目前正在对 Moq 框架进行扩展,以模拟非虚拟方法的实现。我目前已经通过获取原始方法的方法句柄并将其与用户定义的 Func 的指针交换来完成这项工作。
我仍然 运行 关注的一个问题是,当我在 Moq 内部代码(在使用泛型的 class 中)创建 Func 时,我 运行 RuntimeHelpers.PrepareMethod 的问题。 (在我们执行指针交换之前需要准备好Func)。
当我在正常 class(例如程序)中创建完全相同的 Func 时,一切正常。
进一步调查此问题可以追溯到调用 class 是否具有通用参数。
抛出异常:
An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: The given generic instantiation was invalid.
我已将问题隔离在以下代码块中:
class Program
{
static void Main(string[] args)
{
new WithoutGeneric().GoExecute();
new WithGeneric<string>().GoExecute();
}
}
public class WithoutGeneric
{
public void GoExecute()
{
//Works fine
StaticMethods.PrepareThisFunc(() => "Test");
}
}
public class WithGeneric<T>
{
public void GoExecute()
{
//Breaks
StaticMethods.PrepareThisFunc(() => "Test");
}
}
public static class StaticMethods
{
public static void PrepareThisFunc(Func<string> theFunc)
{
RuntimeHelpers.PrepareMethod(theFunc.Method.MethodHandle);
}
}
我也查看了当前的开源 CoreCLR 代码,但未能找出问题所在。
核心CLR:
https://github.com/dotnet/coreclr/blob/master/src/vm/reflectioninvocation.cpp
以下行抛出异常:
2435, 2444, 2447
有没有人知道如何解决这个异常?
CLR 对于 WithGeneric
class 中的类型参数是未知的,它需要知道它才能创建调用图。
这样做可以解决问题:
class Program
{
static void Main(string[] args)
{
new WithoutGeneric().GoExecute();
new WithGeneric<string>().GoExecute();
}
}
public class WithoutGeneric
{
public void GoExecute()
{
//Works fine
StaticMethods.PrepareThisFunc1(() => "Test");
}
}
public class WithGeneric<T>
{
public void GoExecute()
{
//Works fine
StaticMethods.PrepareThisFunc2(() => "Test");
}
}
public static class StaticMethods
{
public static void PrepareThisFunc1(Func<string> theFunc)
{
RuntimeHelpers.PrepareMethod(theFunc.Method.MethodHandle);
}
public static void PrepareThisFunc2(Func<string> theFunc)
{
RuntimeHelpers.PrepareMethod(theFunc.Method.MethodHandle, new[] { typeof(string).TypeHandle });
}
}
我目前正在对 Moq 框架进行扩展,以模拟非虚拟方法的实现。我目前已经通过获取原始方法的方法句柄并将其与用户定义的 Func 的指针交换来完成这项工作。
我仍然 运行 关注的一个问题是,当我在 Moq 内部代码(在使用泛型的 class 中)创建 Func 时,我 运行 RuntimeHelpers.PrepareMethod 的问题。 (在我们执行指针交换之前需要准备好Func)。
当我在正常 class(例如程序)中创建完全相同的 Func 时,一切正常。
进一步调查此问题可以追溯到调用 class 是否具有通用参数。
抛出异常:
An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: The given generic instantiation was invalid.
我已将问题隔离在以下代码块中:
class Program
{
static void Main(string[] args)
{
new WithoutGeneric().GoExecute();
new WithGeneric<string>().GoExecute();
}
}
public class WithoutGeneric
{
public void GoExecute()
{
//Works fine
StaticMethods.PrepareThisFunc(() => "Test");
}
}
public class WithGeneric<T>
{
public void GoExecute()
{
//Breaks
StaticMethods.PrepareThisFunc(() => "Test");
}
}
public static class StaticMethods
{
public static void PrepareThisFunc(Func<string> theFunc)
{
RuntimeHelpers.PrepareMethod(theFunc.Method.MethodHandle);
}
}
我也查看了当前的开源 CoreCLR 代码,但未能找出问题所在。
核心CLR: https://github.com/dotnet/coreclr/blob/master/src/vm/reflectioninvocation.cpp
以下行抛出异常: 2435, 2444, 2447
有没有人知道如何解决这个异常?
CLR 对于 WithGeneric
class 中的类型参数是未知的,它需要知道它才能创建调用图。
这样做可以解决问题:
class Program
{
static void Main(string[] args)
{
new WithoutGeneric().GoExecute();
new WithGeneric<string>().GoExecute();
}
}
public class WithoutGeneric
{
public void GoExecute()
{
//Works fine
StaticMethods.PrepareThisFunc1(() => "Test");
}
}
public class WithGeneric<T>
{
public void GoExecute()
{
//Works fine
StaticMethods.PrepareThisFunc2(() => "Test");
}
}
public static class StaticMethods
{
public static void PrepareThisFunc1(Func<string> theFunc)
{
RuntimeHelpers.PrepareMethod(theFunc.Method.MethodHandle);
}
public static void PrepareThisFunc2(Func<string> theFunc)
{
RuntimeHelpers.PrepareMethod(theFunc.Method.MethodHandle, new[] { typeof(string).TypeHandle });
}
}