2009-09-14 2 views
4

Представьте себе следующую совершенно правовой иерархии типов:Можно ли испускать тип, получаемый из общего типа, при определении себя как параметра типового типа?

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

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

Мой вопрос задается статически скомпилирован определение A <> возможно испускать типа B динамически?

Проблема заключается в том, как указать родительский тип в ModuleBuilder.DefineType.

Или, может быть, есть еще один способ получения такого типа, кроме

  • с использованием указанного выше метода
  • с использованием CodeDom (что очень похоже на создание временного файла и передачи его Csc.exe: -))

EDIT: Тип B должен иметь явный конструктор по умолчанию общественного вызывающему конструктора по умолчанию, унаследованном от A<B>.

+0

Посмотрите на [этот вопрос] (http://stackoverflow.com/questions/1348268/how-do-i-create-a-class-that-inherits-from-another-and-passes -a-типа параметра в). Я думаю, у вас такая же проблема. –

ответ

4

Вы можете использовать перегрузку ModuleBuilder.DefineType, которая не определяет родительский тип, а затем использовать метод TypeBuilder.SetParent для установки родителя рекурсивного типа (используя аргумент что-то вроде typeof(A<>).MakeGenericType(tb) где tb это ваш TypeBuilder, но дон У меня есть компилятор C# передо мной).

EDIT - вот рабочий пример, если у вас есть 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

+0

Не определять (по умолчанию) Методы конструктора работают? –

+0

DefineConstructor возвращает ConstructorBuilder, который используется для испускания кода конструктора. Один из операторов кода должен ссылаться на конструктор базового типа, например: ilg.Emit (OpCodes.Call, ctor); где ctor - это базовый тип экземпляра ConstructorInfo, соответствующий конструктору базового типа. Проблема в том, как получить ctor? Я провалил. – mark

 Смежные вопросы

  • Нет связанных вопросов^_^