Создает ли LambdaExpression.Compile () дополнительную сборку, которая загружается динамически? - PullRequest
1 голос
/ 17 октября 2019

Я хочу иметь несколько подпрограмм, которые динамически создаются с использованием деревьев выражений. Кажется, что самый простой способ их использования - создать LambdaExpression, а затем вызвать LambdaExpression.
Compile(), что приведет к вызываемому делегату.

  • Каковы возможные потери производительноститакого решения?
  • Что именно происходит во время компиляции?
  • Создана и динамически загружена дополнительная сборка с дополнительным новым типом класса?
  • Это происходит каждый раз, когда я вызываю Compile()?
  • Это лучше? создать новый тип и включить все процедуры как статические методы этого типа, используя TypeBuilder и MethodBuilder?

    Любые предложения приветствуются!

1 Ответ

2 голосов
/ 17 октября 2019
  1. этап emit, создание делегата, инициируемого отражением - и, действительно, простое построение дерева выражений - относительно дороги;если вы сделаете это каждый раз, будет больно;однако если вы эффективно кешируете стратегии (то есть вы не строите дерево выражений и не компилируете его постоянно), это прекрасно и разумный способ выполнения метапрограммирования
  2. как правило, генерируется DynamicMethod - это автономный метод, позволяющий избежать всего обычного веса AssemblyBuiler, ModuleBuilder, TypeBuilder и т. д., а просто обеспечивает необработанныйдоступ к ILGenerator методу static стиля;затем код обходит дерево выражений, выдавая соответствующие коды операции через ILGenerator;наконец, CreateDelegate вызывается на DynamicMethod
  3. нет;DynamicMethod пытается избежать этого
  4. да;так что попробуйте кешировать свои стратегии
  5. зависит от контекста;Есть вещи, которые DynamicMethod может сделать, что TypeBuilder не может (например, пропуск доступности), и есть вещи, которые TypeBuilder может сделать, что DynamicMethod не может (реализовать интерфейсы, объявить и использовать поля и т. д. );если вам не нужны эти вещи, Expression.Compile() - это довольно хороший способ избежать необходимости изучать низкоуровневый ref-emit, который очень легко ошибиться *1036* (а неверный IL обычно убивает время выполнения)
  6. (вы не спрашивали 6, но ...) также следует отметить, что Expression может выбрать spoof emit, фактически запустив интерпретатор ASTвместо этого в средах выполнения, которые не позволяют ref-emit;Compile() возвращает точку входа для этого интерпретатора, вместо делегата для динамически скомпилированного метода;эта опция недоступна, если вы используете TypeBuilder
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...