Stashbox by Peter Csajtai

<PackageReference Include="Stashbox" Version="3.1.0-preview-545" />

 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; if (!treeAnalyzer.NestedLambdas.IsEmpty) treeAnalyzer.StoredObjects.AddRange(new object[treeAnalyzer.NestedLambdas.Length]); CompilerContext compilerContext = new CompilerContext(treeAnalyzer.StoredObjects.IsEmpty ? null : new Closure(treeAnalyzer.StoredObjects.AsArray()), 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; } } }