Introduction
Avalanche.Emit is a class library for building Types and emitting opcodes by utilizing Avalanche.Service architecture. This library is a helper to the System.Reflection.Emit namespace.
The following example creates a type with method "int MyFunction(int x) => x < 5 ? 0 : 1;"
// Service that handles assembly builder, module builder and type builder
IService service = Services.Create(Avalanche.Emit.Module.Instance);
// Request to create type builder
IRequestFor<TypeBuilder> typeBuilder = new TypeBuilderRequest("MyClass_", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass);
// Request to create method builder for "MyFunction"
IRequestFor<MethodBuilder> myFunc = new MethodBuilderRequest("MyFunction", MethodAttributes.Public | MethodAttributes.Virtual, null, typeof(int), typeof(int));
// Request to create il generator
IRequestFor<ILGenerator> il = ILGeneratorRequest.Default;
// Define labels
IRequestFor<Label> trueLabel = new LabelRequest(), falseLabel = new LabelRequest();
// "return x < 5 ? 0 : 1"
il = il.Append(OpCodes.Ldarg_1).Append(OpCodes.Ldc_I4_5).Append(OpCodes.Clt).Append(OpCodes.Brtrue_S, falseLabel);
// true: return 1;
il = il.Append(new MarkLabelRequest(trueLabel)).Append(OpCodes.Ldc_I4_1).Append(OpCodes.Ret);
// false: return 0;
il = il.Append(new MarkLabelRequest(falseLabel)).Append(OpCodes.Ldc_I4_0).Append(OpCodes.Ret);
// Add il to "MyFunction"
myFunc = myFunc.Append(il);
// Add "MyFunction"
typeBuilder = typeBuilder.Append(myFunc);
// Request to build type
IRequestFor<Type> type = new TypeRequest(typeBuilder);
// Request to create new instance
IRequestFor<Object> newRequest = type.NewRequest();
// Print request
newRequest.PrintTreeTo(Console.Out);
// Get instance
object instance = service.GetRequired<IRequestFor<object>, object>(newRequest);
// Evaluate: value = 4 < 5 ? 0 : 1;
int value = (int)instance.GetType().GetMethod("MyFunction", new Type[] { typeof(int) })!.Invoke(instance, new object[] { 4 })!;
// Print
Console.WriteLine(value);
View complete request
NewRequest └── Type = TypeRequest └── Key = ContextRequest<TypeBuilder> ├── Key = "System.Reflection.Emit.TypeBuilder" ├── Value = TypeBuilderRequest │ ├── Name = "MyClass_" │ └── Attributes = AutoLayout, AnsiClass, Class, Public, AutoClass └── Requests[0] = ContextRequest<MethodBuilder> ├── Key = "System.Reflection.Emit.Builder" ├── Value = MethodBuilderRequest │ ├── Name = "MyFunction" │ ├── Attributes = PrivateScope, Public, Virtual │ ├── ReturnType = System.Int32 │ └── ParameterTypes[0] = System.Int32 └── Requests[0] = ContextRequest<ILGenerator> ├── Key = "System.Reflection.Emit.ILGenerator" ├── Value = ILGeneratorRequest ├── Requests[0] = Emit │ └── Opcode = ldarg.1 ├── Requests[1] = Emit │ └── Opcode = ldc.i4.5 ├── Requests[2] = Emit │ └── Opcode = clt ├── Requests[3] = Emit │ ├── Opcode = brtrue.s │ └── Parameters[0] = LabelRequest │ └── Id = 49972132 ├── Requests[4] = MarkLabelRequest │ └── Label = LabelRequest │ └── Id = 65204782 ├── Requests[5] = Emit │ └── Opcode = ldc.i4.1 ├── Requests[6] = Emit │ └── Opcode = ret ├── Requests[7] = MarkLabelRequest │ └── Label = LabelRequest ├── Requests[8] = Emit │ └── Opcode = ldc.i4.0 └── Requests[9] = Emit └── Opcode = ret
Full Example
Full example
using System;
using System.Reflection;
using System.Reflection.Emit;
using Avalanche.Emit;
using Avalanche.Service;
public class index
{
public static void Run()
{
{
// <01>
// Service that handles assembly builder, module builder and type builder
IService service = Services.Create(Avalanche.Emit.Module.Instance);
// Request to create type builder
IRequestFor<TypeBuilder> typeBuilder = new TypeBuilderRequest("MyClass_", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass);
// Request to create method builder for "MyFunction"
IRequestFor<MethodBuilder> myFunc = new MethodBuilderRequest("MyFunction", MethodAttributes.Public | MethodAttributes.Virtual, null, typeof(int), typeof(int));
// Request to create il generator
IRequestFor<ILGenerator> il = ILGeneratorRequest.Default;
// Define labels
IRequestFor<Label> trueLabel = new LabelRequest(), falseLabel = new LabelRequest();
// "return x < 5 ? 0 : 1"
il = il.Append(OpCodes.Ldarg_1).Append(OpCodes.Ldc_I4_5).Append(OpCodes.Clt).Append(OpCodes.Brtrue_S, falseLabel);
// true: return 1;
il = il.Append(new MarkLabelRequest(trueLabel)).Append(OpCodes.Ldc_I4_1).Append(OpCodes.Ret);
// false: return 0;
il = il.Append(new MarkLabelRequest(falseLabel)).Append(OpCodes.Ldc_I4_0).Append(OpCodes.Ret);
// Add il to "MyFunction"
myFunc = myFunc.Append(il);
// Add "MyFunction"
typeBuilder = typeBuilder.Append(myFunc);
// Request to build type
IRequestFor<Type> type = new TypeRequest(typeBuilder);
// Request to create new instance
IRequestFor<Object> newRequest = type.NewRequest();
// Print request
newRequest.PrintTreeTo(Console.Out);
// Get instance
object instance = service.GetRequired<IRequestFor<object>, object>(newRequest);
// Evaluate: value = 4 < 5 ? 0 : 1;
int value = (int)instance.GetType().GetMethod("MyFunction", new Type[] { typeof(int) })!.Invoke(instance, new object[] { 4 })!;
// Print
Console.WriteLine(value);
// </01>
}
}
}