Stashbox by Peter Csajtai

<PackageReference Include="Stashbox" Version="3.5.1-preview-621" />

 ILGeneratorExtensions

static class ILGeneratorExtensions
using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; namespace Stashbox.Expressions.Compile.Extensions { internal static class ILGeneratorExtensions { public static LocalBuilder PrepareCapturedArgumentsHolderVariable(this ILGenerator generator, int capturedArgumentsCount) { LocalBuilder localBuilder = generator.DeclareLocal(typeof(object[])); generator.EmitInteger(capturedArgumentsCount); generator.Emit(OpCodes.Newarr, typeof(object)); generator.Emit(OpCodes.Stloc, localBuilder); return localBuilder; } public static void CopyParametersToCapturedArgumentsIfAny(this ILGenerator generator, CompilerContext context, ParameterExpression[] parameters) { int length = context.CapturedArguments.Length; for (int i = 0; i < length; i++) { Expression expression = context.CapturedArguments[i]; int referenceIndex = parameters.GetReferenceIndex(expression); if (referenceIndex != -1) { generator.LoadCapturedArgumentHolder(context); generator.EmitInteger(i); generator.LoadParameter(referenceIndex + ((!context.IsNestedLambda) ? 1 : 2)); if (expression.Type.GetTypeInfo().IsValueType) generator.Emit(OpCodes.Box, expression.Type); generator.Emit(OpCodes.Stelem_Ref); } } } public static bool EmitMethod(this ILGenerator generator, MethodInfo info) { generator.Emit(info.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, info); return true; } public static void LoadCapturedArgumentHolder(this ILGenerator generator, CompilerContext context) { if (!context.IsNestedLambda) generator.Emit(OpCodes.Ldloc, context.CapturedArgumentsHolderVariable); else generator.Emit(context.HasClosure ? OpCodes.Ldarg_1 : OpCodes.Ldarg_0); } public static void EmitInteger(this ILGenerator generator, int intValue) { switch (intValue) { case 0: generator.Emit(OpCodes.Ldc_I4_0); break; case 1: generator.Emit(OpCodes.Ldc_I4_1); break; case 2: generator.Emit(OpCodes.Ldc_I4_2); break; case 3: generator.Emit(OpCodes.Ldc_I4_3); break; case 4: generator.Emit(OpCodes.Ldc_I4_4); break; case 5: generator.Emit(OpCodes.Ldc_I4_5); break; case 6: generator.Emit(OpCodes.Ldc_I4_6); break; case 7: generator.Emit(OpCodes.Ldc_I4_7); break; case 8: generator.Emit(OpCodes.Ldc_I4_8); break; default: if (intValue >= -128 && intValue <= 127) generator.Emit(OpCodes.Ldc_I4_S, (sbyte)intValue); else generator.Emit(OpCodes.Ldc_I4, intValue); break; } } public static void LoadParameter(this ILGenerator generator, int index) { switch (index) { case 0: generator.Emit(OpCodes.Ldarg_0); break; case 1: generator.Emit(OpCodes.Ldarg_1); break; case 2: generator.Emit(OpCodes.Ldarg_2); break; case 3: generator.Emit(OpCodes.Ldarg_3); break; default: if (index <= 255) generator.Emit(OpCodes.Ldarg_S, (byte)index); else generator.Emit(OpCodes.Ldarg, index); break; } } public static void InitValueType(this ILGenerator generator, Type type) { LocalBuilder local = generator.DeclareLocal(type); generator.Emit(OpCodes.Ldloca, local); generator.Emit(OpCodes.Initobj, type); generator.Emit(OpCodes.Ldloc, local); } public static bool TryEmitNumberConstant(this ILGenerator generator, Type type, object value) { if (type == typeof(int)) generator.EmitInteger((int)value); else if (type == typeof(uint)) { generator.EmitInteger((int)(uint)value); } else if (type == typeof(char)) { generator.EmitInteger((char)value); } else if (type == typeof(short)) { generator.EmitInteger((short)value); } else if (type == typeof(byte)) { generator.EmitInteger((byte)value); } else if (type == typeof(ushort)) { generator.EmitInteger((ushort)value); } else if (type == typeof(sbyte)) { generator.EmitInteger((sbyte)value); } else if (type == typeof(long)) { generator.Emit(OpCodes.Ldc_I8, (long)value); } else if (type == typeof(ulong)) { generator.Emit(OpCodes.Ldc_I8, (long)(ulong)value); } else if (type == typeof(float)) { generator.Emit(OpCodes.Ldc_R4, (float)value); } else if (type == typeof(bool)) { generator.Emit(((bool)value) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); } else { if (!(type == typeof(double))) return false; generator.Emit(OpCodes.Ldc_R8, (double)value); } return true; } } }