Можно ли испускать тип, производный от универсального типа, указав себя в качестве параметра универсального типа? - PullRequest
4 голосов
/ 14 сентября 2009

Представьте себе следующую совершенно легальную иерархию типов:

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>.

1 Ответ

4 голосов
/ 14 сентября 2009

Вы можете использовать перегрузку 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...