在泛型类中创建的Func <string>调用RuntimeHelpers.PrepareMethod时不起作用

Dev*_*dse 4 .net c# reflection il runtime-compilation

我目前正在对Moq框架进行扩展,以模拟非虚拟方法的实现。目前,我已经通过获取原始方法的方法句柄并将其与用户定义的Func的指针进行交换来进行此工作。

我仍然遇到的一个问题是,当我在Moq内部代码中(在使用泛型的类中)创建Func时,遇到了RuntimeHelpers.PrepareMethod的问题。(在执行指针交换之前,需要准备Func)。

当我在普通类(例如Program)中创建完全相同的Func时,一切正常。

进一步调查该问题可以追溯到调用类是否具有通用参数。

抛出异常:

An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll

Additional information: The given generic instantiation was invalid.
Run Code Online (Sandbox Code Playgroud)

我在以下代码块中隔离了该问题:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我也查看了当前的开源CoreCLR代码,但无法找出问题所在。

CoreCLR:https : //github.com/dotnet/coreclr/blob/master/src/vm/reflectioninvocation.cpp

发生以下异常:2435、2444、2447

是否有人对如何解决此异常有任何想法?

Yog*_*esh 5

CLR对于WithGeneric类中的type参数是未知的,创建调用图需要知道它。

这样做可以解决问题:

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 });
    }
}
Run Code Online (Sandbox Code Playgroud)