Reflection Emit and Type Inheritance: Calling Base Type Constructors

Suppose you want to use Reflection.Emit to generate a dynamic type in memory. Suppose this dynamic type should inherit a custom base type, and you want to put the default implementation into this base type. In plain C#, you would write…

class MyDynamic : MyBase
    public MyDynamic()

… but with Reflection.Emit, there’s a gotcha.

The C# code above shows a class with a default constructor. No base constructor is explicitly called. In this case, the C# compiler automatically adds a call to the base classes default constructor. This is a feature of the compiler, not the CLR! Using Reflection.Emit, you must add the call to the base constructor yourself, since you’re skipping the C# compiler.

If you forget to call the base constructor, the base class won’t work as in regular C# code. You might encounter strange exceptions (probably lots of NullReferenceException or InvalidOperationException).

The following code show how to generate a class with a default constructor that calls its base constructor.

// We want to create a type that inherits "MyBaseType" and calls its default constructor.
var baseType = typeof(MyBaseType);
var baseConstructor = baseType.GetConstructor(BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance, null, new Type[0], null);

// Create a Type Builder that generates a type directly into the current AppDomain.
var appDomain = AppDomain.CurrentDomain;
var assemblyName = new AssemblyName("MyDynamicAssembly");
var assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name);

var typeBuilder = moduleBuilder.DefineType("MyDynamicType", TypeAttributes.Class | TypeAttributes.Public, baseType);

var ilGenerator = constructor.GetILGenerator();

// Create a parameterless (default) constructor.
var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);

// Generate constructor code
ilGenerator.Emit(OpCodes.Ldarg_0);                // push "this" onto stack.
ilGenerator.Emit(OpCodes.Call, baseConstructor);  // call base constructor

ilGenerator.Emit(OpCodes.Nop);                    // C# compiler add 2 NOPS, so
ilGenerator.Emit(OpCodes.Nop);                    // we'll add them, too.

ilGenerator.Emit(OpCodes.Ret);                    // Return

If you need to pass parameters to the base constructor, you can change the code above as follows:

ilGenerator.Emit(OpCodes.Ldarg_0);                // push "this"
ilGenerator.Emit(OpCodes.Ldarg_1);                // push the 1. parameter
ilGenerator.Emit(OpCodes.Ldarg_2);                // push the 2. parameter
ilGenerator.Emit(OpCodes.Ldarg_3);                // push the 3. parameter
ilGenerator.Emit(OpCodes.Call, baseConstructor);

This post shows how to add properties to the generated type.

Freelance full-stack .NET and JS developer and architect. Located near Cologne, Germany.

Leave a Reply

Your email address will not be published. Required fields are marked *