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?
CodePudding user response:
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
.