Каковы некоторые профессионалы/недостатки для использования Отражения. Испустить библиотеку по сравнению с CodeDOM для того, чтобы динамично сгенерировать код во времени выполнения?
Я пытаюсь генерировать некоторых (относительно сложный) динамические классы в системе на основе метаданных, доступных во времени выполнения в форме XML. Я буду генерировать классы, которые расширяют существующие классы в блоке приложения, реализовывая дополнительные интерфейсы, добавляя методы, и переопределяя виртуальных и абстрактных участников.
Я хочу удостовериться, что я выбираю соответствующую технику, прежде чем я стану слишком глубоким в реализацию. Любая информация о том, как эти различные методы генерации кода отличаются, была бы полезна. Кроме того, любая информация о библиотеках с открытым исходным кодом, которые упрощают или оптимизировали работу, увядает, любой API был бы полезен также.
Я думаю, что ключевые моменты о 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
(но, конечно, это зависит от вашего конкретного сценария).
Код, ориентированный на CodeDom, как правило, легче поддерживать, поскольку вы генерируете код C #, а не IL (больше людей могут читать C #, чем IL). Более того, если вы ошиблись в коде CodeDom, вы получите ошибку компилятора; если вы генерируете недопустимый IL, вы получаете фатальное исключение или сбой.
Однако, поскольку CodeDom вызывает компилятор csc.exe
, подготовка кода к использованию выполняется немного медленнее. С Reflection.Emit вы можете генерировать код прямо в памяти.
CodeDom, вероятно, подходит для большинства вещей; его используют XmlSerializer
и конструктор WinForms.
Вы можете посмотреть ExpandoObject
. Однако это только .NET 4.0.