2015-02-15 4 views
1

Чтобы создать экземпляр класса с использованием Reflection.Emit Мне нужно указать OpCodes.Newobj, однако для этого требуется конструктор созданного класса. Итак, если я пишу свой собственный компилятор, как мне создать код для метода, который создает экземпляр другого класса, который определен в исходном коде (а не в библиотеке времени исполнения)?Создание объекта с использованием Reflection.Emit в простом компиляторе

Я создаю код за 2 прохода, сначала создаю TypeBuilder для каждого класса, который у меня есть, и добавляю к ним меток, чтобы на них можно ссылаться во время второго прохода. Однако я не могу назвать TypeBuilder.CreateType для этих заглушек, потому что получаю исключение, Reflection.Emit требует, чтобы все методы были определены и имеют тело. Но в то же время я не могу закончить создание кода для метода, который должен создать экземпляр класса, который был определен в исходном коде.

Итак, как создать код для этого:

class Foo 
{ 
} 

class Bar 
{ 
    Foo DoSomething() 
    { 
     return new Foo(); 
    } 
} 

и это:

class Foo 
{ 
    public Foo Create() 
    { 
     return new Foo(); 
    } 
} 
+0

Это может быть выполнено с Reflection.Emit, но не все задачи, которые может потребоваться компилятору, возможны: http://blogs.msdn.com/b/lucian/archive/2009/11/29/the- limits-of-reflection-emit.aspx –

ответ

1

Вам нужно три прохода:

  1. создать TypeBuilder для каждого класса
  2. для каждого класса, создайте MethodBuilder для каждого меня mber, включая конструкторы
  3. для каждого класса, сгенерировать тела методов с использованием ILGenerator. Как вы закончите перебор методы по каждому классу, называют CreateType()

Когда вы испускаете newobj, вы можете передать ConstructorBuilder, представляющий конструктор, который означает, что класс и конструктор не должен быть заморожены еще.

+0

А, правда, моя ошибка заключалась в том, что в моем тестовом коде я использовал TypeBuilder.GetConstructor(), чтобы получить конструктор по умолчанию, и этот метод должен был быть создан первым. Но я должен создать свой собственный конструктор и передать MethodBuilder, как вы сказали. Благодарю. – dubik

+0

"вы можете передать' MethodBuilder', представляющий конструктор "Не имеете в виду' ConstructorBuilder'? – svick

+0

@svick: Да, я думал, что это то же самое, но это только «MethodBase», который разделяется между конструкторами и обычными методами, а иерархия выходит за рамки этого. –