2009-09-14 48 views
4

想象一下以下完全合法的类型层次:是否有可能发出从泛型类型派生的类型,同时将自身指定为泛型类型参数?

class A<T> where T : A<T> 
{ 
} 

class B : A<B> 
{ 
    public B():base(){} 
} 

我的问题是给的<的静态编译定义>是它可以动态地发出B型?

问题是如何在ModuleBuilder.DefineType中指定父类型。

或者,也许还有另一种方式产生这种类型,除了

  • 使用利用CodeDom中(这是很象创建临时文件并把它传递给CSC.EXE上述方法
  • : - ))

编辑: 类型B应该有明确的公共默认构造函数调用从继承的默认构造函数。

+0

看看[这个问题](http://stackoverflow.com/questions/1348268/how-do-i-create-a-class-that-inherits-from-another-and-passes -a型参数中)。我认为你有同样的问题。 – 2009-09-14 12:17:19

回答

4

您可以使用ModuleBuilder.DefineType超载不指定父类型,然后使用TypeBuilder.SetParent方法父设置为递归式(使用参数类似typeof(A<>).MakeGenericType(tb)其中tb是你TypeBuilder,但我不在我面前没有C#编译器)。

编辑 - 这里是一个工作示例,假设你有一个ModuleBuilder mb。对于一个空的默认构造函数,根本不需要使用DefineConstructor方法;或者你可以使用DefineDefaultConstructor。我已经包含了一个示例,其中显式调用了基础构造函数,但是,如果您想在其中添加一些额外的逻辑。

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(); 
+0

仍然有问题。尝试生成默认的构造函数,当然,它应该调用基类型的默认构造函数。 – mark 2009-09-15 10:54:54

+0

不定义(默认)构造函数方法的工作? – 2009-09-15 11:03:44

+0

DefineConstructor返回ConstructorBuilder,它用于发出构造函数的代码。其中一个代码语句应该调用基类型的构造函数,像这样 - ilg.Emit(OpCodes.Call,ctor);其中ctor是与基类型的构造函数相对应的基类型ConstructorInfo实例。问题是如何获得ctor?我失败了。 – mark 2009-09-15 11:36:46