RuntimeHelpers.PrepareMethod не работает при вызове с Func‹строкой›, созданной в классе Generic

В настоящее время я работаю над расширением фреймворка Moq, чтобы также издеваться над реализацией не виртуальных методов. В настоящее время я уже работаю, получая дескриптор метода исходного метода и заменяя его указателем определяемого пользователем Func.

Одна проблема, с которой я все еще сталкиваюсь, заключается в том, что когда я создаю Func во внутреннем коде Moq (внутри класса, использующего Generics), я сталкиваюсь с проблемой с RuntimeHelpers.PrepareMethod. (Func должен быть подготовлен, прежде чем мы сможем выполнить замену указателя).

Когда я создаю точно такой же Func в обычном классе (например, Program), все работает нормально.

Дальнейшее исследование проблемы проследило это до того, имел ли класс вызова общие аргументы или нет.

Выбрасывается исключение:

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 с открытым исходным кодом, но не смог выяснить, в чем может быть проблема.

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

Исключение выбрасывается на строки: 2435, 2444, 2447

Кто-нибудь знает, как разрешить это исключение?


person Devedse    schedule 31.07.2015    source источник


Ответы (1)


Среде CLR неизвестен параметр типа в классе WithGeneric, который необходимо знать для создания графа вызовов.

Это решит проблему:

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 });
    }
}
person Yogesh    schedule 31.07.2015
comment
У меня похожая проблема Если у вас есть время - person johnny 5; 17.01.2020