2014-12-31 4 views
0

Меня интересует теоретический аспект. В чем необходимость в C# для использования выражений Codedom/Reflection или Lambda/деревьев выражений для генерации кода во время выполнения в типичном повседневном сценарии программирования? не в специализированных случаяхЗачем мне нужно компилировать/генерировать методы/код во время выполнения?

или на других языках, таких как Ruby, зачем использовать monkeypatching для добавления/изменения классов во время выполнения?

Как это может быть преимуществом?

+2

По моему опыту, это в основном для конкретных вещей. Подумайте о библиотеках сериализации, которые генерируют код сериализации с использованием отражения и IL-излучения, поэтому вам не нужно писать и поддерживать этот код вручную. Выражения полезны для перевода кода, например, в SQL-запросы. Однако Monkeypatching позволяет вам заменять/отменять существующие функции, что может привести к большой путанице. Выглядит полезно при написании тестового кода. –

ответ

2

В Ruby используются методы генерации методов везде.

Например, существуют способы получения инкубационных и геттер методы:

class Module 
    def attr_reader(*attributes) 
    attributes.each do |attribute| 
     define_method(attribute) do instance_variable_get(:"@#{attribute}") end 
    end 
    end 

    def attr_writer(*attributes) 
    attributes.each do |attribute| 
     define_method(:"#{attribute}=") do |value| 
     instance_variable_set(:"@#{attribute}", value) 
     end 
    end 
    end 

    def attr_accessor(*attributes) 
    attr_reader(*attributes) 
    attr_writer(*attributes) 
    end 
end 

Когда слово один из этих методов, как это:

attr_reader :bla 

Это создаст метод, названный bla, который возвращает значение переменной экземпляра с именем @bla.

И

attr_writer :bla 

сгенерирует метод, названный bla= (присвоение имен метода с знаком равенства в конце концов, это обычное соглашение об именах для сеттеров в Ruby), который присваивает свой аргумент в переменный экземпляре с именем @bla.

class Foo 
    attr_reader :foo, :bar 
    attr_writer :baz, :quux 
    attr_accessor :gargle, :blarf 
end 

Это будет генерировать методы foo, bar, baz=, quux=, gargle, gargle=, blarf, blarf=.

Другим примером является ORM-библиотека ActiveRecord для Ruby, которая генерирует методы getter и setter, а также методы поиска для моделей, основанные на отражении по схеме базы данных во время выполнения.

ActiveRecord также имеет методы динамического поиска, которые позволяют вам делать что-то вроде Person.find_by_name_and_age('John', 42). Конечно, существует бесконечно много комбинаций столбцов базы данных, которые можно было бы искать, поэтому нецелесообразно создавать все методы заранее. Вместо этого ActiveRecord устанавливает привязку method_missing для перехвата вызовов к несуществующим методам, начиная с find_by_. Однако, как только он перехватил вызов метода, он генерирует метод этого имени в предположении, что метод может быть вызван чаще всего за это время, и, таким образом, динамический перехват может быть подвергнут второстепенному.

Вообще говоря, это код Синтез полезен везде, где Генерация кода полезно, но со значительным преимуществом, что

  • не загромождать исходного дерева, потому что все это порождало «код "является эфемерным
  • Вы используете собственные возможности языков для генерации кода, поэтому он будет (в некотором смысле) всегда корректным, тогда как при генерации кода (простого текстового) вам придется позаботиться о создании синтаксически допустимого кода
1

Я столкнулся с несколькими случаями. Один случай - по соображениям производительности. например когда вы сохраняете скомпилированный делегат, который создает объект. Например, с некоторыми структурами IoC. Эти скомпилированные делегаты, как правило, не спешат создавать, но очень быстро выполнять могут предложить хорошее повышение производительности, если один и тот же делегат вызывается много раз.

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

1

Иногда вам приходится жертвовать полным чистым кодом, чтобы получить большую производительность и изменчивость.

Например, если вы разработали 1000 классов и создали для каждого класса двоичный сериализатор. это действительно легко сделать путем отражения и генерации кода. Менее сложно поддерживать уникальный динамический код, чем много статического кода. После полной квалификации динамического кода риск действительно минимизирован.

удачи, общий обложка хорошая часть этой проблемы.

Генерировать msil во время выполнения бесполезно, когда вы работаете над небольшим проектом.

Еще одно соображение касается горизонтального развития (коммунальные услуги/помощники), не зависящего от прямого развития бизнеса.