Подтвердить что ты не робот

Reflection.Emit против CodeDOM

Каковы некоторые плюсы и минусы для использования библиотеки Reflection.Emit против CodeDOM для динамического генерации кода во время выполнения?

Я пытаюсь сгенерировать некоторые (относительно сложные) динамические классы в системе, основанной на метаданных, доступных во время выполнения в форме XML. Я буду генерировать классы, расширяющие существующие классы в сборке приложений, реализацию дополнительных интерфейсов, добавление методов и переопределение виртуальных и абстрактных элементов.

Я хочу, чтобы я выбрал подходящую технику, прежде чем я углубился в реализацию. Любая информация о том, как эти разные методы генерации кода отличается, была бы полезной. Кроме того, любая информация о библиотеках с открытым исходным кодом, которые упрощают или оптимизируют работу, увядают либо API, также полезны.

4b9b3361

Ответ 1

Я думаю, что ключевые моменты в CodeDOM и Reflection.Emit следующие:

  • CodeDom генерирует исходный код С# и обычно используется при создании кода, который должен быть включен как часть решения и скомпилирован в среде IDE (например, классы LINQ to SQL, WSDL, XSD все работают таким образом). В этом случае вы также можете использовать частичные классы для настройки сгенерированного кода. Он менее эффективен, потому что он генерирует источник С#, а затем запускает компилятор для его анализа (снова!) И скомпилирует его. Вы можете генерировать код, используя относительно высокоуровневые конструкции (похожие на выражения и выражения С#), такие как циклы.

  • Reflection.Emit генерирует IL, поэтому он непосредственно создает сборку, которая также может храниться только в памяти. В результате намного эффективнее. Вы должны генерировать IL-код низкого уровня (значения хранятся в стеке, цикл должен быть реализован с использованием переходов), поэтому создание более сложной логики немного сложно.

В общем, я считаю, что Reflection.Emit обычно рассматривается как предпочтительный способ генерации кода во время выполнения, в то время как CodeDOM является предпочтительным при создании кода перед компиляцией. В вашем сценарии, оба из них, вероятно, будут работать нормально (хотя CodeDOM может потребоваться более высокие привилегии, потому что на самом деле нужно вызвать С# -компилятор, который является частью любой установки .NET).

Другой вариант - использовать класс Expression. В .NET 4.0 он позволяет генерировать код, эквивалентный выражениям и операторам С#. Однако это не позволяет создавать классы. Таким образом, вы можете комбинировать это с Reflection.Emit(для создания классов, которые делегируют реализацию в код, сгенерированный с помощью Expression). Для некоторых сценариев вам также может не понадобиться полноценная иерархия классов - часто словарь динамически сгенерированных делегатов, таких как Dictionary<string, Action>, может быть достаточно хорошим (но, конечно, это зависит от вашего точного сценария).

Ответ 2

Код, который нацелен на CodeDom, как правило, проще поддерживать, поскольку вы генерируете код С#, а не IL (больше людей могут читать С#, чем IL). Более того, если вы ошиблись в коде CodeDom, вы получите ошибку компилятора; если вы создаете неверный IL, вы получаете фатальное исключение или сбой.

Однако, поскольку CodeDom вызывает компилятор csc.exe, он немного медленнее, чтобы код был готов к использованию. С Reflection.Emit вы можете сгенерировать код непосредственно в память.

CodeDom, вероятно, подходит для большинства вещей; XmlSerializer и конструктор WinForms используют его.

Ответ 3

Возможно, вы захотите посмотреть ExpandoObject. Однако это только .NET 4.0.