Stashbox by Peter Csajtai

<PackageReference Include="Stashbox" Version="3.2.2" />

 ExpressionEmitter

static class ExpressionEmitter
using Stashbox.Expressions.Compile.Emitters; using Stashbox.Expressions.Compile.Extensions; using System; using System.Linq; using System.Linq.Expressions; using System.Reflection.Emit; namespace Stashbox.Expressions.Compile { internal static class ExpressionEmitter { public static bool TryEmit(this LambdaExpression expression, out Delegate resultDelegate) { return expression.Body.TryEmit(out resultDelegate, expression.Type, expression.ReturnType, expression.Parameters.ToArray()); } public static bool TryEmit(this Expression expression, out Delegate resultDelegate, Type delegateType, Type returnType, params ParameterExpression[] parameters) { resultDelegate = null; TreeAnalyzer treeAnalyzer = new TreeAnalyzer(); if (!treeAnalyzer.Analyze(expression, parameters)) return false; object[] array = treeAnalyzer.Constants.AsArray(); if (treeAnalyzer.NestedLambdas.Length > 0) array = array.Append(new object[treeAnalyzer.NestedLambdas.Length]); CompilerContext compilerContext = new CompilerContext((array.Length == 0) ? null : new Closure(array), treeAnalyzer.Constants, treeAnalyzer.DefinedVariables, treeAnalyzer.CapturedParameters, treeAnalyzer.NestedLambdas); DynamicMethod dynamicMethod = Emitter.CreateDynamicMethod(compilerContext, returnType, parameters); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (compilerContext.HasCapturedVariablesArgument) { compilerContext.CapturedArgumentsHolderVariable = iLGenerator.PrepareCapturedArgumentsHolderVariable(treeAnalyzer.CapturedParameters.Length); iLGenerator.CopyParametersToCapturedArgumentsIfAny(compilerContext, parameters); } if (treeAnalyzer.DefinedVariables.Length > 0) compilerContext.LocalBuilders = treeAnalyzer.DefinedVariables.BuildLocals(iLGenerator); if (!expression.TryEmit(iLGenerator, compilerContext, parameters)) return false; iLGenerator.Emit(OpCodes.Ret); resultDelegate = (compilerContext.HasClosure ? dynamicMethod.CreateDelegate(delegateType, compilerContext.Target) : dynamicMethod.CreateDelegate(delegateType)); return true; } } }