问题
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
- using the aforementioned method
- using CodeDom (which is much like creating a temporary file and passing it to csc.exe :-))
EDIT:
The type B should have explicit public default constructor invoking the default constructor inherited from A<B>.
回答1:
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();
来源:https://stackoverflow.com/questions/1421149/is-it-possible-to-emit-a-type-deriving-from-a-generic-type-while-specifying-itse