Imagine the following perfectly legal type hierarchy:
class A<T> where T : A<T>
{
}
class B : A<B>
{
public B():base(){}
}
My question is given a statically compiled definition of A<> is it possible to emit the type B dynamically?
The problem is how to specify the parent type in ModuleBuilder.DefineType
.
Or maybe there is another way to produce such a type, other than
EDIT:
The type B
should have explicit public default constructor invoking the default constructor inherited from A<B>
.
You can use an overload of ModuleBuilder.DefineType
which doesn't specify a parent type, and then use the TypeBuilder.SetParent
method to set the parent to the recursive type (using an argument something like typeof(A<>).MakeGenericType(tb)
where tb
is your TypeBuilder
, but I don't have a C# compiler in front of me).
EDIT - here's a working example, assuming you've got a ModuleBuilder mb
. For an empty default constructor, you don't need to use the DefineConstructor
method at all; alternatively you could use DefineDefaultConstructor
. I've included an example where the base constructor is explicitly called, though, in case you have some extra logic you want to add in there.
TypeBuilder tb = mb.DefineType("B");
Type AB = typeof(A<>).MakeGenericType(tb);
tb.SetParent(AB);
ConstructorInfo ctor = TypeBuilder.GetConstructor(AB, typeof(A<>).GetConstructor(new Type[] { }));
ILGenerator ilg = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { }).GetILGenerator();
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Call, ctor);
ilg.Emit(OpCodes.Ret);
Type t = tb.CreateType();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With