Reflection.Emit против CodeDOM - PullRequest
       33

Reflection.Emit против CodeDOM

47 голосов
/ 03 марта 2010

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

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

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

Ответы [ 3 ]

58 голосов
/ 03 марта 2010

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

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

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

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

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

16 голосов
/ 03 марта 2010

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

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

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

7 голосов
/ 03 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...