Skip to content

Instantly share code, notes, and snippets.

@NickStrupat
Created January 30, 2025 01:58
Show Gist options
  • Save NickStrupat/c9ab1986ecc6ef04d03797c0bc10ab8e to your computer and use it in GitHub Desktop.
Save NickStrupat/c9ab1986ecc6ef04d03797c0bc10ab8e to your computer and use it in GitHub Desktop.
Write runnable, runtime emitted assemblies to disk with .NET 9
using System;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
var assemblyPath = "test.dll";
//CreateAndSaveAssembly(assemblyPath);
UseAssembly(assemblyPath);
;
static void CreateAndSaveAssembly(string assemblyPath)
{
PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(
new AssemblyName("MyAssembly"),
typeof(object).Assembly
);
TypeBuilder tb = ab.DefineDynamicModule("MyModule")
.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
MethodBuilder entryPoint = tb.DefineMethod(
"Main",
MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static
);
ILGenerator il = entryPoint.GetILGenerator();
// ...
il.EmitWriteLine("Hello World!");
il.Emit(OpCodes.Ret);
tb.CreateType();
MetadataBuilder metadataBuilder = ab.GenerateMetadata(
out BlobBuilder ilStream,
out BlobBuilder fieldData
);
PEHeaderBuilder peHeaderBuilder = new PEHeaderBuilder(
imageCharacteristics: Characteristics.ExecutableImage);
ManagedPEBuilder peBuilder = new ManagedPEBuilder(
header: peHeaderBuilder,
metadataRootBuilder: new MetadataRootBuilder(metadataBuilder),
ilStream: ilStream,
mappedFieldData: fieldData,
entryPoint: MetadataTokens.MethodDefinitionHandle(entryPoint.MetadataToken)
);
BlobBuilder peBlob = new BlobBuilder();
peBuilder.Serialize(peBlob);
using var fileStream = new FileStream(assemblyPath, FileMode.Create, FileAccess.Write);
peBlob.WriteContentTo(fileStream);
}
static void UseAssembly(string assemblyPath)
{
Assembly assembly = Assembly.LoadFrom(assemblyPath);
var type = assembly.GetType("MyType") ?? throw new("no type found");
MethodInfo? method = type?.GetMethod("Main") ?? throw new("no method found");
Console.WriteLine(method?.Invoke(null, null));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment