Альтернативы 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, используйте этот сайт.