Как стать автором
Обновить

Комментарии 29

По-моему эффективнее использовать IL.Emit
Думаю, что программирование на IL это не для тех, кому некогда… Цель представленной библиотеки — сделать встраивание в программу динамического кода рутинным, простейшим делом. Главным было сэкономить время разработчика, предоставить инструмент для программирования «на скорую руку».
Emit и CSharpCodeProvider — это как ассемблер и язык высокого уровня. Честно говоря, тяжело написать серьезный код на Emit. Хотя бы потому, что в случае ошибок разобраться в нем намного сложнее. А вот C#-код вполне можно вытащить и посмотреть, что там так или не так.

Интересно конечно было бы сравнить производительность, но в общем, не думаю, что она будет меньше, чем у обычного кода на C#. А позволяет ли Emit реально ускорить код? Интересно было бы услышать тех, кто сталкивался с этим на практике. У меня же слишком разные применения были — на C# писались и компилировались на лету полноценные классы с определенной логикой. А Emit — тут скорее короткие выражения. И то давно. Последнее время совсем переехал на CSharpCodeProvider.
Думаю, речь про эффективность на стадии генерации кода. Во время исполнения особой разницы быть не должно.
Сомневаюсь, что Emit позволит сколько-нибудь значительно сэкономить время выполнения. Если вы учитываете время парсинга исходного текста на C# — то да, может быть какую-то мизерную выгоду даст. Если же вас интересует возможность получения на Reflection.Emit более эффективного кода, нежели тот, что получается на выходе у компилятора C# — это нереально.
Лучше уж Linq.Expressions :-)
У автора тоже есть ссылка на эту библиотеку, хотелось бы в двух словах узнать в чем разница. Преимущества и недостатки той и другой.
Отлично, спасибо! Посмотрел код — всё чисто и понятно. Только assemblyCash — это про наличные деньги, а кеширование — это cache :)
Увидел графопостроитель и вспомнил, как делал в школе похожее, вызывая интерпретатор qbasic через командную строку, чтобы вычислять выражения. Работало не очень быстро :)
Главный вопрос: зачем это нужно? Пока я вижу это как хороший способ превратить код в кашу.
Статью-то читали? Там примеры есть.
Читали. Меня интересуют примеры из реальной жизни, а не програмка, которая картинки по формуле рисует.
Мы системы диффуров решаем подобным образом на Java. По пользовательской модели генерируем Java-класс, компилируем и загружаем в рантайме.
Хм, интересно. Меньше кода выходит, чем если создавать объекты более традиционно, прикидывали?
Что вы подразумеваете под «более традиционно»? Работает гораздо быстрее, вот основная цель.
Реальный пример. В системе существуют user-defined поля. Значения этих полей вычисляются пользователем на основании его кастомной логики. Логика пишется на C#/VB.
А что это за приложение вообще, где юзеру писать код на C# надо? Не Python/Lua, не DSL какой-нибудь, а С#?
Финансовая индустрия. И код пишут, конечно же, не конечные пользователи системы, код пишут implementation инженеры, которые настраивают систему под нужды конкретного заказчика. Пользователь и знать не знает, что там под капотом.
Не буду спешить с выводами, допустим были причины отказаться от конфигов в пользу такого экзотического решения. Но я бы его избегал до последнего так как:

1. Усложняется структура приложения за счет всех этих песочниц.
2. Код менее читаемый.
3. Как написано в статье, потенциальный источник утечек памяти.
Как вы настроите в конфиге совершенно произвольные бизнес-правила?
Я думал, здесь о динамическом программировании. Ну или накрайняк о динамической типизации. По-моему, топик назван неудачно. Что-нибудь типа «Генерация кода в рантайме» было бы ближе…
Название топика изменил. И в тексте… Спасибо.
В этом варианте, мы задали формулу отдельно, а значения параметров отдельно. Метод ExecuteCode проверяет, нет ли среди ранее скомпилированных им сборок, подходящей для выполнения текущего вызова. Если исходный C#-код, возвращаемый им тип, а также типы и имена параметров совпадают, то можно использовать приготовленную при первом вызове ExecuteCode сборку повторно.

У меня помню была похожая задача, но я её решал компиляцией в одной и той же сборке, просто делал god-object статический класс, у которого генерировал методы, после этого эти методы сохранялись в делегат, а делегат отдавался (если надо) наружу. То есть оверхед вызова однажды скомпилированной функции был исключительно в Delegate.Invoke(object[])

Хотя у вас конечно задача меньше регламентирована.
Добавил раздел про ограничения на параметры и возвращаемое значение при работе сгенерированного кода в песочнице. Это существенно — можно использовать только сериализуемые типы и типы, производные от MarshalByRefObject.
Переделал код для .Net 2.0 (требования программы) и включил в качестве дополнения в мат. программу SMath Studio.

У меня есть вопрос по поводу создаваемых сборок. Где они создаются? Лень опять в дебри исходников влезать. Хочу быть уверенным, что не мусорю в системе. Сборки удаляются после использования?

Когда использовал код в отдельном приложении, то сборки были рядом, а когда положил код в отдельный плагин, то концов найти не могу.
Классная библиотека. Очень удобно подготавливать сборку к исполнению в одну-две строчки.
А вы не думали оформить её в виде NuGet пакета?
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.