Search code examples
c#.net-corereflection.net-5reflection.emit

Cannot create dynamic type in .NET Core


I want to add Child as a dynamic type to a dynamic assembly:

public abstract class Parent { }       // I want to define this statically

public class Child : Parent {          // I want to define this dynamically
  private Child() : base() { }
}

I followed this example.

I added the nuget package System.Reflection.Emit (v 4.7.0).

Then wrote this:

using System;
using System.Reflection;
using System.Reflection.Emit;

public abstract class Base { }

public class Program {

  public static void Main() {

    // define dynamic assembly
    var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()), AssemblyBuilderAccess.Run);
    var moduleBuilder = assemblyBuilder.DefineDynamicModule(Guid.NewGuid().ToString());

    // define dynamic type
    var typeName = "Child";
    var typeBuilder = moduleBuilder.DefineType(
      typeName,
      TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout,
      typeof(Base));
    typeBuilder.DefineDefaultConstructor(MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
    //typeBuilder.CreateType();   // this was missing - see accepted answer below

    // test it
    try {
      typeBuilder.Assembly.GetTypes();                 // <--- throws
    }
    catch (ReflectionTypeLoadException exception) {
      Console.WriteLine(exception.Message);
    }
  }

}

It throws this:

Unable to load one or more of the requested types. Could not load type 'Child' from assembly '28266a72-fc60-44ac-8e3c-3ba7461c6be4, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

This failed for me in a unit testing project. It also failed on dotnetfiddle.

What have I done wrong?


Solution

  • You forgot to call CreateType. As the documentation says:

    Before a type is used, the TypeBuilder.CreateType method must be called. CreateType completes the creation of the type.

    You might not need to use the Type object that it returns for anything, but you still need to do this. Loading the type counts as "using the type" after all.

    You should do:

    typeBuilder.CreateType();
    

    after you DefineDefaultConstructor.