Альтернативы CompileToMethod в стандарте .Net

Теперь я переношу некоторую библиотеку, которая использует выражения в приложении .Net Core и столкнулась с проблемой, что вся моя логика основана на LambdaExpression.CompileToMethod, который просто отсутствует. Вот пример кода:

public static MethodInfo CompileToInstanceMethod(this LambdaExpression expression, TypeBuilder tb, string methodName, MethodAttributes attributes)
{
    ...

    var method = tb.DefineMethod($"<{proxy.Name}>__StaticProxy", MethodAttributes.Private | MethodAttributes.Static, proxy.ReturnType, paramTypes);
    expression.CompileToMethod(method);

    ...
}

Можно ли каким-либо образом переписать его, чтобы дать возможность генерировать методы с использованием выражений? Я уже могу сделать это с помощью Emit, но он довольно сложный, и я бы хотел его избежать в пользу высокоуровневых выражений.

Я попытался использовать var method = expression.Compile().GetMethodInfo();, но в этом случае я получаю сообщение об ошибке:

System.InvalidOperationException: невозможно импортировать глобальный метод или поле из другого модуля.

Я знаю, что я могу испускать IL вручную, но мне нужно точно преобразовать Expression → в MethodInfo, привязанный к определенному TypeBuilder, вместо того, чтобы строить себя DynamicMethod на нем.

Ответ 1

Это не идеальное решение, но стоит подумать, не хотите ли вы писать все с нуля:

  • Если вы посмотрите на реализацию CompileToMethod, вы увидите, что под капотом он использует внутренний класс LambdaCompiler.
  • Если вы копаете еще глубже, вы увидите, что LambdaCompiler использует System.Reflection.Emit для преобразования lambdas в MethodInfo.
  • System.Reflection.Emit поддерживается .NET Core.
  • Учитывая это, мое предложение состоит в том, чтобы попытаться повторно использовать исходный код LambdaCompiler. Вы можете найти здесь здесь.

Самая большая проблема с этим решением заключается в следующем:

  • LambdaCompiler распространяется среди многих файлов, поэтому может быть громоздко найти то, что необходимо для его компиляции.
  • LambdaCompiler может использовать некоторый API, который вообще не поддерживается .NET Core.

Несколько дополнительных комментариев:

  • Если вы хотите проверить, какой API поддерживается, используя платформу .NET API Catalog.
  • Если вы хотите увидеть различия между стандартными версиями .NET, используйте этот сайт.