Skip to content

Instantly share code, notes, and snippets.

@kosmakoff
Created November 30, 2016 20:18
Show Gist options
  • Save kosmakoff/d5a2d006624919b0487b63610b2193fd to your computer and use it in GitHub Desktop.
Save kosmakoff/d5a2d006624919b0487b63610b2193fd to your computer and use it in GitHub Desktop.
Simple class that builds the type implementing arbitrary interface in-memory, and then constructs it and returns
using System;
using System.Reflection;
using System.Reflection.Emit;
namespace CodeGenDemo
{
static class CodeGenerator
{
public static T GenerateStub<T>()
{
var interfaceType = typeof(T);
var typeName = "StubFor" + interfaceType.Name.TrimStart('I');
var assemblyName = new AssemblyName("DynamicAssembly");
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var module = assemblyBuilder.DefineDynamicModule("DynamicModule");
var typeBuilder = module.DefineType(typeName, TypeAttributes.Public);
typeBuilder.AddInterfaceImplementation(interfaceType);
var methods = interfaceType.GetMethods();
var objType = typeof(object);
var objCtor = objType.GetConstructor(Type.EmptyTypes);
// add constructor
var constructorMethodInfo = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
var ilGenerator = constructorMethodInfo.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Call, objCtor);
ilGenerator.Emit(OpCodes.Ret);
foreach (var methodInfo in methods)
{
var returnType = methodInfo.ReturnType;
if (returnType == typeof(int))
{
var intMethodBuilder = typeBuilder.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(int), Type.EmptyTypes);
ilGenerator = intMethodBuilder.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldc_I4, 42);
ilGenerator.Emit(OpCodes.Ret);
typeBuilder.DefineMethodOverride(intMethodBuilder, methodInfo);
}
if (returnType == typeof(string))
{
var stringMethodBuilder = typeBuilder.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(string), Type.EmptyTypes);
ilGenerator = stringMethodBuilder.GetILGenerator();
var lb1 = ilGenerator.DefineLabel();
ilGenerator.Emit(OpCodes.Ldstr, "Hello, World!");
ilGenerator.Emit(OpCodes.Ret);
typeBuilder.DefineMethodOverride(stringMethodBuilder, methodInfo);
}
}
var type = typeBuilder.CreateType();
var constructor = type.GetConstructor(Type.EmptyTypes);
var instance = (T)constructor.Invoke(new object[0]);
return instance;
}
}
}
@kosmakoff
Copy link
Author

Usage note

Only interfaces with methods with no params and returning int and string are supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment