Alternatives of CompileToMethod in .Net Standard
Disclaimer: I am author of the library.
I have created Expression Compiler, which has similar API to that of Linq Expressions, with slight changes. https://github.com/yantrajs/yantra/wiki/Expression-Compiler
var a = YExpression.Parameter(typeof(int));
var b = YExpression.Parameter(typeof(int));
var exp = YExpression.Lambda<Func<int,int,int>>("add",
YExpression.Binary(a, YOperator.Add, b),
new YParameterExpression[] { a, b });
var fx = exp.CompileToStaticMethod(methodBuilder);
Assert.AreEqual(1, fx(1, 0));
Assert.AreEqual(3, fx(1, 2));
This library is part of JavaScript compiler we have created. We are actively developing it and we have added features of generators and async/await in JavaScript, so Instead of using Expression Compiler, you can create debuggable JavaScript code and run C# code easily into it.
It is not an ideal solution but it is worth considering if you don't want to write everything from the scratch:
- If you look on
CompileToMethod
implementation, you will see that under the hood it uses internalLambdaCompiler
class. - If you dig even deeper, you willl see that
LambdaCompiler
usesSystem.Reflection.Emit
to convert lambdas intoMethodInfo
. System.Reflection.Emit
is supported by .NET Core.- Taking this into account, my proposition is to try to reuse the
LambdaCompiler
source code. You can find it here.
The biggest problem with this solution is that:
LambdaCompiler
is spread among many files so it may be cumbersome to find what is needed to compile it.LambdaCompiler
may use some API which is not supported by .NET Core at all.
A few additional comments:
- If you want to check which API is supported by which platform use .NET API Catalog.
- If you want to see differences between .NET standard versions use this site.
I ran into the same issue when porting some code to netstandard. My solution was to compile the lambda to a Func using the Compile method, store the Func in a static field that I added to my dynamic type, then in my dynamic method I simply load and call the Func from that static field. This allows me to create the lambda using the LINQ Expression APIs instead of reflection emit (which would have been painful), but still have my dynamic type implement an interface (which was another requirement for my scenario).
Feels like a bit of a hack, but it works, and is probably easier than trying to recreate the CompileToMethod functionality via LambdaCompiler.